Thanks for clarification. Regarding the sharing, is 0 specifying that the application does not require sharing or is a requirement for that segment to be private?
Alex On 22 October 2014 16:18, Savolainen, Petri (NSN - FI/Espoo) < [email protected]> wrote: > 0 is the default => with current flag definitions: both SW + HW can > access, not shared with external processes. > > > > -Petri > > > > *From:* ext Alexandru Badicioiu [mailto:[email protected]] > *Sent:* Wednesday, October 22, 2014 4:01 PM > *To:* Ciprian Barbu > *Cc:* Bill Fischofer; Savolainen, Petri (NSN - FI/Espoo); > [email protected] > > *Subject:* Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support API > > > > The option of creating buffer pools out of memory regions does not solve > existing applications portability problem. The odp_pktio application > expects packets to be allocated in shared memory regions. Is this a > semantic that should be satisfied by all platforms? > > odp_shm_create takes a flag argument which has two values for > linux-generic: > > /* > > * Shared memory flags > > */ > > > > /* Share level */ > > #define ODP_SHM_SW_ONLY 0x1 /**< Application SW only, no HW access */ > > #define ODP_SHM_PROC 0x2 /**< Share with external processes */ > > > > but odp_pktio uses 0. Could we assume that this value has a kind of > ODP_SHM_PACKET meaning? > > We could also explicitly extend this flag list to work across platforms. > > > > Alex > > > > > > > > > > > > On 22 October 2014 14:59, Ciprian Barbu <[email protected]> wrote: > > On Wed, Oct 22, 2014 at 2:47 PM, Ciprian Barbu <[email protected]> > wrote: > > This thread has been cold for 5 days, so the assumption is that we can > > go forward with the design right now. This patch series proposed by > > Bala updates some part of the API to the final form of the Buffer > > Design Document, we should have it merged if there are no more > > objections. For that more people with the right expertise should have > > a look at it and get the thread back on track. > > > > I for example have observed the following issue. All the examples > > create buffer pools over shared memory, which doesn't make sense for > > some platforms, linux-dpdk for example, which ignores the base_addr > > argument altogether. I think we need more clarity on this subject, for > > sure the creation of buffer pools will differ from platform to > > platform, which migrates to the application responsibility. > > > > I think we should have a helper function to easily create buffer pools > > without worrying too much about the difference in buffer management > > between platforms, so that one can write a simple portable application > > with no sweat. For the hardcore programmers the API still gives fine > > control to buffer management that depending on the platform could > > involve additional prerequisites, like creating a shared memory > > segment to hold the buffer pool. > > Ok, so I had another look at the Buffer Management final design. I now > see that the option of creating buffer pools from regions has been > removed, so in this case things will be simpler for the applications. > In other words we should really start working on the full > implementation of the API because from there the problem I just stated > above (having to create shared memory segments) will disappear. > > > > > > On Fri, Oct 17, 2014 at 4:33 PM, Bill Fischofer > > <[email protected]> wrote: > >> Let's consider the implications of removing segmentation support from > >> buffers and only having that concept be part of packets. > >> > >> The first question that arises is what is the relationship between the > >> abstract types odp_packet_t and odp_buffer_t? This is important because > >> currently we say that packets are allocated from ODP buffer pools, not > from > >> packet pools. Do we need a separate odp_packet_pool_t that is used for > >> packets? > >> > >> Today, when I allocate a packet I'm allocating a single object that > happens > >> to be a single buffer object of type ODP_BUFFER_TYPE_PACKET. But that > only > >> works if the two objects have compatible semantics (including > segmentation). > >> If the semantics are not compatible, then an odp_packet_t may in fact be > >> composed of multiple odp_buffer_t's because the packet may consist of > >> multiple segments and buffers no longer recognize the concept of > segments so > >> a single buffer can only be a single segment. > >> > >> So now an odp_packet_segment_t may be an odp_buffer_t but an > odp_packet_t in > >> fact is some meta-object that is constructed (by whom?) from multiple > >> odp_packet_segment_ts that are themselves odp_buffer_ts. So > >> odp_packet_to_buffer() no longer makes sense since there is no longer a > >> one-to-one correspondence between packets and buffers. We could have an > >> odp_packet_segment_to_buffer() routine instead. > >> > >> Next question: What about meta data? If an odp_packet_t is a type of an > >> odp_buffer_t then this is very straightforward since all buffer meta > data is > >> reusable as packet meta data and the packet type can just add its own > >> specific meta data to this set. But if an odp_packet_t is now a > separate > >> object then where does the storage for its meta data come from? If we > try to > >> map it into an odp_buffer_t that doesn't work since an odp_packet_t may > >> consist of multiple underlying odp_buffer_ts, one for each > >> odp_packet_segment_t. Is the packet meta data duplicated in each > segment? > >> Is the first segment of a packet special (odp_packet_first_segment_t)? > And > >> what about user meta data, since this is of potentially variable size? > >> > >> I submit that there are a lot of implications to this that need to be > fully > >> thought through, which is why I believe it's simpler to keep > segmentation as > >> part of buffers that (for now) only happens to be used by a particular > type > >> of buffer, namely packets. > >> > >> Bill > >> > >> On Fri, Oct 17, 2014 at 8:05 AM, Ola Liljedahl < > [email protected]> > >> wrote: > >>> > >>> Personally I don't see any need for segmentation support in buffers. I > am > >>> just trying to shoot down what I think is flawed reasoning. > >>> > >>> -- Ola#1 > >>> > >>> On 17 October 2014 15:03, Ola Liljedahl <[email protected]> > wrote: > >>>> > >>>> But segmentation is already needed in a current and known subclass > (i.e. > >>>> packets). We are not talking about some other feature which we don't > know if > >>>> it will be needed. So this is not a case of "just in case". > >>>> > >>>> -- Ola#1 > >>>> > >>>> > >>>> On 17 October 2014 14:45, Ola Dahl <[email protected]> wrote: > >>>>> > >>>>> Hi, > >>>>> > >>>>> I do not think it is wise to put features in the base class "just in > >>>>> case" they would be needed in some future (not yet known) subclass. > >>>>> > >>>>> So if the concept of segmentation is relevant for packets but not for > >>>>> timers then I think it should be implemented as a feature of packets. > >>>>> > >>>>> Best regards, > >>>>> > >>>>> Ola D > >>>>> > >>>>> On Fri, Oct 17, 2014 at 2:33 PM, Bill Fischofer > >>>>> <[email protected]> wrote: > >>>>>> > >>>>>> I agree that packets are the buffer type that most likely uses > >>>>>> segments, however there are many advantages to putting this support > in the > >>>>>> base class rather than the subclass independent of the number of > buffer > >>>>>> subclasses that will use this support today. > >>>>>> > >>>>>> It's simpler > >>>>>> It's more extensible > >>>>>> It results in cleaner and more efficient application code > >>>>>> > >>>>>> Allow me to expand on these points. First simplicity. Call the > work > >>>>>> required to support segmentation in the implementation X. That X > is going > >>>>>> to be pretty much constant no matter where it is done. But if the > >>>>>> implementation has a choice between doing X at a low level vs. > doing it at a > >>>>>> high level then it's simpler for the implementation to do it once > and be > >>>>>> done with it. If the implementation does it at a higher level then > it is > >>>>>> either constrained to map that higher-level implementation to be > built on a > >>>>>> set of lower-level functions that may or may not be appropriate or > else it > >>>>>> needs to do a completely parallel implementation that is optimal > but highly > >>>>>> duplicative. > >>>>>> > >>>>>> Extensibility should be clear. If at some future point we decide > >>>>>> segmentation would be useful for some new buffer type (e.g., IPC) > then > >>>>>> that's trivial to do if the base class supports it and awkward if > it's only > >>>>>> part of packets. > >>>>>> > >>>>>> From an application standpoint, it's cleaner because the packet APIs > >>>>>> are just wrappers around their corresponding buffer APIs and can be > mapped > >>>>>> directly. Otherwise we have a set of APIs that don't map and are > not easily > >>>>>> translatable. > >>>>>> > >>>>>> With regard to efficient segment access, that's what the > >>>>>> odp_packet_addr() routine provides--one-step fast-path > addressability to the > >>>>>> first segment of a packet. An odp_packet_t is an abstract opaque > type. It > >>>>>> is not, and cannot be treated as an address by the application. > >>>>>> > >>>>>> Does that make sense? > >>>>>> > >>>>>> Bill > >>>>>> > >>>>>> > >>>>>> > >>>>>> > >>>>>> On Fri, Oct 17, 2014 at 5:37 AM, Savolainen, Petri (NSN - FI/Espoo) > >>>>>> <[email protected]> wrote: > >>>>>>> > >>>>>>> Hi, > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> 1. The only segmentation use case is for segmented packet, not for > >>>>>>> segmented buffers. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> 2. Common case for packets is that everything application needs is > in > >>>>>>> the first segment. Odp_packet_t could refer always into that “first > >>>>>>> segment”, so that application (in the common case) would not need > to use > >>>>>>> odp_packet_seg_xxx() calls at all – only odp_packet_xxx() calls. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> When buffer level features are minimized, the need for > >>>>>>> odp_buffer_xxx(odp_packet_to_buffer(pkt),...) is minimized. All > packet > >>>>>>> manipulation should happen through odp_packet_xxx(pkt, …) calls. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> -Petri > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> From: ext Bill Fischofer [mailto:[email protected]] > >>>>>>> Sent: Friday, October 17, 2014 1:17 PM > >>>>>>> To: Savolainen, Petri (NSN - FI/Espoo) > >>>>>>> Cc: ext Jacob, Jerin; [email protected] > >>>>>>> > >>>>>>> > >>>>>>> Subject: Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support > API > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> I'm not sure how to understand these two statements: > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> 1. There's no use case for segmented buffers > >>>>>>> > >>>>>>> 2. We should optimize for the common case (with segments) > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> These seem contradictory. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> The use case for segmented buffers is that some platforms have a > >>>>>>> HW-defined and managed segmented buffer model. If we insist that > the > >>>>>>> application be able to specify and control packet segment sizes we > are > >>>>>>> making the decision to exclude such platforms from supporting > ODP. The > >>>>>>> optimization suggested is precisely what is being proposed here. > By default > >>>>>>> packets are assumed to be contained in implementation-managed > segmented > >>>>>>> buffers and the first segment will be large enough to contain all > packet > >>>>>>> headers for non-pathological cases. The case where the > application wishes > >>>>>>> to traverse the entire packet in SW is expected to be rare because > in the > >>>>>>> data plane you simply do not have the cycles to do this at line > rate for all > >>>>>>> packets. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> As for having both odp_buffer_xxx() and odp_packet_xxx() APIs, > this is > >>>>>>> simply syntax to avoid the constant need for explicit conversion > functions > >>>>>>> since unlike C++, C does not support generic functions. So you > cannot pass > >>>>>>> an odp_packet_t to a function that expects an odp_buffer_t > argument without > >>>>>>> a conversion call. Do we really want to force applications to > constantly be > >>>>>>> writing code like: > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> odp_buffer_xxx(odp_packet_to_buffer(pkt),...) > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> rather than > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> odp_packet_xxx(pkt,...) > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> Not only is this awkward, it is also inefficient. By having the > >>>>>>> explicit odp_packet_xxx() calls, the implementation is free to > optimize > >>>>>>> these references in whatever manner is appropriate to that > implementation. > >>>>>>> For some this may be a simple preprocessor-type expansion while > for others > >>>>>>> there may be more sophisticated handling. But the application > should > >>>>>>> neither know nor care about how the implementation chooses to do > this. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> On Fri, Oct 17, 2014 at 2:27 AM, Savolainen, Petri (NSN - FI/Espoo) > >>>>>>> <[email protected]> wrote: > >>>>>>> > >>>>>>> Hi, > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> This is also my opinion. There’s no use case for segmented buffers > in > >>>>>>> v1.0 - so let’s keep it simple and define that buffers (and thus > buffer > >>>>>>> pools) are always unsegmented. Segmentation comes into play only > with > >>>>>>> packets (and only with those packets that cannot fit into a single > buffer). > >>>>>>> For example, if implementation has max buffer size 256, any > packets larger > >>>>>>> than that are segmented and segments are handled with > packet_seg_xxx calls. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> Also, I’d propose that we optimize for the common case (with > segments) > >>>>>>> - so that the odp_packet_t handle would refer always to the head > of packet > >>>>>>> segment. If the first segment (data/data_len pointed by the > odp_packet_t) > >>>>>>> carries all data application is interested in (=protocol headers), > the > >>>>>>> application would not have to use the segment API at all. Most > applications > >>>>>>> would not see any difference between small/large or > segmented/unsegmented > >>>>>>> packets as long as all headers fit into the first segment. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> -Petri > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> From: [email protected] > >>>>>>> [mailto:[email protected]] On Behalf Of ext Jacob, > Jerin > >>>>>>> Sent: Friday, October 17, 2014 9:34 AM > >>>>>>> To: Bill Fischofer > >>>>>>> Cc: [email protected] > >>>>>>> Subject: Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support > API > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> The need for segment API infrastructure is very clear.The question > is, > >>>>>>> Do we need separate APIs for > >>>>>>> > >>>>>>> segment management at odp_buffer_segment* AND odp_packet_segment* > >>>>>>> levels ? > >>>>>>> > >>>>>>> as ODP_BUFFER_TYPE_TIMEOUT and ODP_BUFFER_TYPE_RAW will be always > >>>>>>> unsegmented and if there is a > >>>>>>> > >>>>>>> API for odp_packet_segement* then there will be not be any consumer > >>>>>>> for odp_buffer_segment* API for 1.0 > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> ________________________________ > >>>>>>> > >>>>>>> From: Bill Fischofer <[email protected]> > >>>>>>> Sent: Thursday, October 16, 2014 9:08 PM > >>>>>>> To: Jacob, Jerin > >>>>>>> Cc: Ola Liljedahl; Balasubramanian Manoharan; > [email protected] > >>>>>>> Subject: Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support > API > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> From the buffer design doc (p. 8-9): > >>>>>>> > >>>>>>> Buffer Pool Options > >>>>>>> > >>>>>>> The odp_buffer_opts_e enum is used to specify additional options > >>>>>>> relating to the buffer pool. Buffer pool options defined are: > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> · ODP_BUFFER_OPTS_NONE > >>>>>>> > >>>>>>> · ODP_BUFFER_OPTS_UNSEGMENTED > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> These options are additive so an application can simply specify a > >>>>>>> buf_opts by ORing together the options needed. Note that buffer > pool > >>>>>>> options are themselves OPTIONAL and a given implementation MAY > fail the > >>>>>>> buffer pool creation request with an appropriate errno if the > requested > >>>>>>> option is not supported by the underlying ODP implementation, with > the > >>>>>>> exception that UNSEGMENTED pools MUST be supported for non-packet > types and > >>>>>>> for packet types as long as the requested size is less than the > >>>>>>> implementation-defined native packet segment size. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> Use ODP_BUFFER_OPTS_NONE to specify default buffer pool options > with > >>>>>>> no additions. The ODP_BUFFER_OPTS_UNSEGMENTED option specifies > that the > >>>>>>> buffer pool should be unsegmented. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> So unsegmented buffer pool support is available. As far as RAW > >>>>>>> buffers go, again from the doc (p. 14): > >>>>>>> > >>>>>>> ODP_BUFFER_TYPE_RAW > >>>>>>> > >>>>>>> This is the “basic” buffer type which simply consists of a single > >>>>>>> fixed-sized block of contiguous memory. Buffers of this type do > not support > >>>>>>> user meta data and the only built-in meta data supported for this > type of > >>>>>>> buffer are those that are statically computable, such as pool and > size. This > >>>>>>> type of buffer is entirely under application control and most of > the buffer > >>>>>>> APIs defined in this document are not available. APIs for this > type of > >>>>>>> buffer are described in this document. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> So RAW buffers are always unsegmented. The intent is that Packets > are > >>>>>>> by default segmented but can be unsegmented while the other buffer > types are > >>>>>>> by default unsegmented but (with the exception of RAW buffers) can > be made > >>>>>>> segmented. This is because all buffers start out as a single > segment and > >>>>>>> hence are unsegmented until they are expanded to overflow that > single > >>>>>>> segment. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> Hope that clarifies things. Again, this is all very > straightforward > >>>>>>> and only comes into play when actually needed. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> On Wed, Oct 8, 2014 at 4:03 AM, Jacob, Jerin > >>>>>>> <[email protected]> wrote: > >>>>>>> > >>>>>>> If there is no valid use case for supporting segmentation for raw > >>>>>>> buffers then lets drop it. At least it will reduce the effort of > >>>>>>> > >>>>>>> implementing and testing/verification buffer APIs on different > >>>>>>> platforms. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> ________________________________ > >>>>>>> > >>>>>>> From: [email protected] > >>>>>>> <[email protected]> on behalf of Ola Liljedahl > >>>>>>> <[email protected]> > >>>>>>> Sent: Wednesday, October 8, 2014 1:37 PM > >>>>>>> To: Balasubramanian Manoharan > >>>>>>> Cc: [email protected] > >>>>>>> Subject: Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support > API > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> As I wrote in my comment to the architecture discussion yesterday, > I > >>>>>>> am against segmentation for buffers. Or at least there must be the > >>>>>>> possibility to create a buffer pool with guaranteed non-segmented > buffers. > >>>>>>> Segmented packets are OK but not all usages for buffers relate to > packets. A > >>>>>>> lot of internal usages (timeouts, SW messages, internal data > structures) > >>>>>>> will not be able to handle segmented buffers so you must be able > to force > >>>>>>> the creation of buffer pools with non-segmented buffers. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> -- Ola > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> On 8 October 2014 09:50, Balasubramanian Manoharan > >>>>>>> <[email protected]> wrote: > >>>>>>> > >>>>>>> This patch contains ODP Buffer Management missing APIs > >>>>>>> The intent of this patch is to port the missing APIs from Buffer > >>>>>>> Management design document into Linux-generic repo. > >>>>>>> The dummy functions will be replaced during linux-generic > >>>>>>> implementation. > >>>>>>> > >>>>>>> Signed-off-by: Balasubramanian Manoharan < > [email protected]> > >>>>>>> --- > >>>>>>> platform/linux-generic/include/api/odp_buffer.h | 203 > >>>>>>> ++++++++++++++++++++- > >>>>>>> .../linux-generic/include/api/odp_buffer_pool.h | 30 +++ > >>>>>>> platform/linux-generic/odp_buffer.c | 120 > ++++++++++++ > >>>>>>> platform/linux-generic/odp_buffer_pool.c | 7 + > >>>>>>> 4 files changed, 351 insertions(+), 9 deletions(-) > >>>>>>> > >>>>>>> diff --git a/platform/linux-generic/include/api/odp_buffer.h > >>>>>>> b/platform/linux-generic/include/api/odp_buffer.h > >>>>>>> index d8577fd..aeb75ed 100644 > >>>>>>> --- a/platform/linux-generic/include/api/odp_buffer.h > >>>>>>> +++ b/platform/linux-generic/include/api/odp_buffer.h > >>>>>>> @@ -28,8 +28,34 @@ extern "C" { > >>>>>>> */ > >>>>>>> typedef uint32_t odp_buffer_t; > >>>>>>> > >>>>>>> -#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */ > >>>>>>> +/** > >>>>>>> +* ODP buffer segment > >>>>>>> +*/ > >>>>>>> +typedef uint32_t odp_buffer_segment_t; > >>>>>>> > >>>>>>> +/** > >>>>>>> +* ODP buffer type > >>>>>>> +*/ > >>>>>>> +typedef enum odp_buffer_type { > >>>>>>> + ODP_BUFFER_TYPE_INVALID = -1, /**< Buffer type invalid */ > >>>>>>> + ODP_BUFFER_TYPE_ANY = 0, /**< Buffer that can hold > any > >>>>>>> other > >>>>>>> + buffer type */ > >>>>>>> + ODP_BUFFER_TYPE_RAW = 1, /**< Raw buffer, > >>>>>>> + no additional metadata */ > >>>>>>> + ODP_BUFFER_TYPE_PACKET = 2, /**< Packet buffer */ > >>>>>>> + ODP_BUFFER_TYPE_TIMEOUT = 3 /**< Timeout buffer */ > >>>>>>> +} odp_buffer_type_e; > >>>>>>> + > >>>>>>> +/** > >>>>>>> +* ODP buffer options > >>>>>>> +*/ > >>>>>>> +typedef enum odp_buffer_opts { > >>>>>>> + ODP_BUFFER_OPTS_NONE, > >>>>>>> + ODP_BUFFER_OPTS_UNSEGMENTED > >>>>>>> +} odp_buffer_opts_e; > >>>>>>> + > >>>>>>> +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */ > >>>>>>> +#define ODP_SEGMENT_INVALID (0xffffffff) /**< Invalid segment */ > >>>>>>> > >>>>>>> /** > >>>>>>> * Buffer start address > >>>>>>> @@ -58,14 +84,6 @@ size_t odp_buffer_size(odp_buffer_t buf); > >>>>>>> */ > >>>>>>> int odp_buffer_type(odp_buffer_t buf); > >>>>>>> > >>>>>>> -#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */ > >>>>>>> -#define ODP_BUFFER_TYPE_ANY 0 /**< Buffer that can hold any > >>>>>>> other > >>>>>>> - buffer type */ > >>>>>>> -#define ODP_BUFFER_TYPE_RAW 1 /**< Raw buffer, no > additional > >>>>>>> metadata */ > >>>>>>> -#define ODP_BUFFER_TYPE_PACKET 2 /**< Packet buffer */ > >>>>>>> -#define ODP_BUFFER_TYPE_TIMEOUT 3 /**< Timeout buffer */ > >>>>>>> - > >>>>>>> - > >>>>>>> /** > >>>>>>> * Tests if buffer is valid > >>>>>>> * > >>>>>>> @@ -76,6 +94,110 @@ int odp_buffer_type(odp_buffer_t buf); > >>>>>>> int odp_buffer_is_valid(odp_buffer_t buf); > >>>>>>> > >>>>>>> /** > >>>>>>> + * Tests if buffer is segmented > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle > >>>>>>> + * > >>>>>>> + * @return 1 if buffer has more than one segment, > >>>>>>> + * otherwise 0 > >>>>>>> + */ > >>>>>>> + > >>>>>>> +int odp_buffer_is_segmented(odp_buffer_t buf); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Get address and size of user meta data associated with a buffer > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle > >>>>>>> + * @param[out] udata_size Number of bytes of user meta data > >>>>>>> available > >>>>>>> + * at the returned address > >>>>>>> + * @return Address of the user meta data for > this > >>>>>>> buffer > >>>>>>> + * or NULL if the buffer has no user > meta > >>>>>>> data. > >>>>>>> + */ > >>>>>>> +void *odp_buffer_udata(odp_buffer_t buf, size_t *udata_size); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Get address of user meta data associated with a buffer > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle > >>>>>>> + * > >>>>>>> + * @return Address of the user meta data for this > buffer > >>>>>>> + * or NULL if the buffer has no user meta > data. > >>>>>>> + */ > >>>>>>> +void *odp_buffer_udata_addr(odp_buffer_t buf); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Get count of number of segments in a buffer > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle > >>>>>>> + * > >>>>>>> + * @return Count of the number of segments in buf > >>>>>>> + */ > >>>>>>> +size_t odp_buffer_segment_count(odp_buffer_t buf); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Get the segment identifier for a buffer segment by index > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle > >>>>>>> + * @param[in] ndx Segment index of segment of interest > >>>>>>> + * > >>>>>>> + * @return Segment identifier or ODP_SEGMENT_INVALID > if > >>>>>>> the > >>>>>>> + * supplied ndx is out of range. > >>>>>>> + */ > >>>>>>> +odp_buffer_segment_t odp_buffer_segment_by_index(odp_buffer_t buf, > >>>>>>> size_t ndx); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Get the next segment identifier for a buffer segment > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle > >>>>>>> + * @param[in] seg Segment identifier of the previous segment > >>>>>>> + * > >>>>>>> + * @return Segment identifier of the next segment, > >>>>>>> + or ODP_SEGMENT_INVALID. > >>>>>>> + */ > >>>>>>> +odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf, > >>>>>>> + odp_buffer_segment_t > >>>>>>> seg); > >>>>>>> +/** > >>>>>>> + * Get start address for a specified buffer segment > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle > >>>>>>> + * @param[in] seg Segment identifier of the buffer to be > >>>>>>> addressed > >>>>>>> + * @param[out] seglen Returned number of bytes in this buffer > >>>>>>> + * segment available at returned address > >>>>>>> + * > >>>>>>> + * @return Segment start address or NULL > >>>>>>> + */ > >>>>>>> +void *odp_buffer_segment_map(odp_buffer_t buf, > odp_buffer_segment_t > >>>>>>> seg, > >>>>>>> +size_t *seglen); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + *Unmap a buffer segment > >>>>>>> + * > >>>>>>> + * @param[in] seg Buffer segment handle > >>>>>>> + */ > >>>>>>> +void odp_buffer_segment_unmap(odp_buffer_segment_t seg); > >>>>>>> + > >>>>>>> +/** > >>>>>>> +* Get start address for a specified buffer offset > >>>>>>> +* > >>>>>>> +* @param[in] buf Buffer handle > >>>>>>> +* @param[in] offset Byte offset within the buffer to be > addressed > >>>>>>> +* @param[out] seglen Returned number of bytes in this buffer > >>>>>>> +* segment available at returned address > >>>>>>> +* > >>>>>>> +* @return Offset start address or NULL > >>>>>>> +*/ > >>>>>>> +void *odp_buffer_offset_map(odp_buffer_t buf, size_t offset, > >>>>>>> +size_t *seglen); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Unmap a buffer segment by offset > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle > >>>>>>> + * @param[in] offset Buffer offset > >>>>>>> + */ > >>>>>>> +void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset); > >>>>>>> + > >>>>>>> +/** > >>>>>>> * Print buffer metadata to STDOUT > >>>>>>> * > >>>>>>> * @param buf Buffer handle > >>>>>>> @@ -83,6 +205,69 @@ int odp_buffer_is_valid(odp_buffer_t buf); > >>>>>>> */ > >>>>>>> void odp_buffer_print(odp_buffer_t buf); > >>>>>>> > >>>>>>> +/** > >>>>>>> + * Split a buffer into two buffers at a specified split point > >>>>>>> + * > >>>>>>> + * @param[in] buf Handle of buffer to split > >>>>>>> + * @param[in] offset Byte offset within buf to split buffer > >>>>>>> + * > >>>>>>> + * @return Buffer handle of the created split buffer > >>>>>>> + */ > >>>>>>> +odp_buffer_t odp_buffer_split(odp_buffer_t buf, size_t offset); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Join two buffers into a single buffer > >>>>>>> + * > >>>>>>> + * @param[in] buf1 Buffer handle of first buffer to join > >>>>>>> + * @param[in] buf2 Buffer handle of second buffer to join > >>>>>>> + * > >>>>>>> + * @return Buffer handle of the joined buffer > >>>>>>> + */ > >>>>>>> +odp_buffer_t odp_buffer_join(odp_buffer_t buf1, odp_buffer_t > buf2); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Trim a buffer at a specified trim point > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle of buffer to trim > >>>>>>> + * @param[in] offset byte offset within buf to trim > >>>>>>> + * > >>>>>>> + * @return Handle of the trimmed buffer or > >>>>>>> + * ODP_BUFFER_INVALID if the operation was not > >>>>>>> performed > >>>>>>> + */ > >>>>>>> +odp_buffer_t odp_buffer_trim(odp_buffer_t buf, size_t offset); > >>>>>>> +/** > >>>>>>> + * Extend a buffer for a specified number of bytes > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle of buffer to expand > >>>>>>> + * @param[in] ext size, in bytes, of the extent to add to the > >>>>>>> + * existing buffer. > >>>>>>> + * > >>>>>>> + * @return Handle of the extended buffer or > >>>>>>> ODP_BUFFER_INVALID > >>>>>>> + * if the operation was not performed > >>>>>>> + */ > >>>>>>> +odp_buffer_t odp_buffer_extend(odp_buffer_t buf, size_t ext); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Clone a buffer, returning an exact copy of it > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle of buffer to duplicate > >>>>>>> + * > >>>>>>> + * @return Handle of the duplicated buffer or > >>>>>>> ODP_BUFFER_INVALID > >>>>>>> + * if the operation was not performed > >>>>>>> + */ > >>>>>>> +odp_buffer_t odp_buffer_clone(odp_buffer_t buf); > >>>>>>> + > >>>>>>> +/** > >>>>>>> + * Copy a buffer, returning an exact copy of it > >>>>>>> + * > >>>>>>> + * @param[in] buf Buffer handle of buffer to copy > >>>>>>> + * > >>>>>>> + * @return Handle of the copied buffer or > >>>>>>> ODP_BUFFER_INVALID > >>>>>>> + * if the operation was not performed > >>>>>>> + */ > >>>>>>> +odp_buffer_t odp_buffer_copy(odp_buffer_t buf); > >>>>>>> + > >>>>>>> + > >>>>>>> > >>>>>>> #ifdef __cplusplus > >>>>>>> } > >>>>>>> diff --git a/platform/linux-generic/include/api/odp_buffer_pool.h > >>>>>>> b/platform/linux-generic/include/api/odp_buffer_pool.h > >>>>>>> index fe88898..f85d96c 100644 > >>>>>>> --- a/platform/linux-generic/include/api/odp_buffer_pool.h > >>>>>>> +++ b/platform/linux-generic/include/api/odp_buffer_pool.h > >>>>>>> @@ -52,6 +52,27 @@ odp_buffer_pool_t odp_buffer_pool_create(const > char > >>>>>>> *name, > >>>>>>> > >>>>>>> > >>>>>>> /** > >>>>>>> + * Get the next buffer pool from its predecessor > >>>>>>> + * > >>>>>>> + * @param[in] pool Buffer pool handle > >>>>>>> + * @param[out] name Name of the pool > >>>>>>> + * (max ODP_BUFFER_POOL_NAME_LEN - 1 > >>>>>>> chars) > >>>>>>> + * @param[out] udata_size Size of user meta data used by this > >>>>>>> pool. > >>>>>>> + * @param[out] buf_num Number of buffers contained in this > >>>>>>> pool > >>>>>>> + * @param[out] buf_size Default size of application data in > >>>>>>> each buffer > >>>>>>> + * @param[out] buf_type Buffer type of the pool > >>>>>>> + * @param[out] buf_opts Buffer options for this pool > >>>>>>> + * @param[out] predef Predefined (1) or Created (0). > >>>>>>> + * > >>>>>>> + * @return Buffer pool handle > >>>>>>> + */ > >>>>>>> +odp_buffer_pool_t odp_buffer_pool_next(odp_buffer_pool_t pool, > >>>>>>> + char *name, size_t > *udata_size, > >>>>>>> + size_t *buf_num, size_t > >>>>>>> *buf_size, > >>>>>>> + enum odp_buffer_type > *buf_type, > >>>>>>> + enum odp_buffer_opts > *buf_opts, > >>>>>>> + uint32_t *predef); > >>>>>>> +/** > >>>>>>> * Find a buffer pool by name > >>>>>>> * > >>>>>>> * @param name Name of the pool > >>>>>>> @@ -80,6 +101,15 @@ void odp_buffer_pool_print(odp_buffer_pool_t > >>>>>>> pool); > >>>>>>> */ > >>>>>>> odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool); > >>>>>>> > >>>>>>> +/** > >>>>>>> +* Allocate a buffer from a buffer pool > >>>>>>> +* > >>>>>>> +* @param[in] pool Pool handle > >>>>>>> +* @param[in] size Size of object to store in buffer > >>>>>>> +* > >>>>>>> +* @return Buffer handle or ODP_BUFFER_INVALID > >>>>>>> +*/ > >>>>>>> +odp_buffer_t odp_buffer_alloc_size(odp_buffer_pool_t pool, size_t > >>>>>>> size); > >>>>>>> > >>>>>>> /** > >>>>>>> * Buffer free > >>>>>>> diff --git a/platform/linux-generic/odp_buffer.c > >>>>>>> b/platform/linux-generic/odp_buffer.c > >>>>>>> index e54e0e7..7f4b4f0 100644 > >>>>>>> --- a/platform/linux-generic/odp_buffer.c > >>>>>>> +++ b/platform/linux-generic/odp_buffer.c > >>>>>>> @@ -45,6 +45,21 @@ int odp_buffer_is_valid(odp_buffer_t buf) > >>>>>>> return (handle.index != ODP_BUFFER_INVALID_INDEX); > >>>>>>> } > >>>>>>> > >>>>>>> +int odp_buffer_is_segmented(odp_buffer_t buf) > >>>>>>> +{ > >>>>>>> + odp_buffer_hdr_t *buf_hdr = odp_buf_to_hdr(buf); > >>>>>>> + > >>>>>>> + if (buf_hdr->scatter.num_bufs == 0) > >>>>>>> + return 0; > >>>>>>> + else > >>>>>>> + return 1; > >>>>>>> +} > >>>>>>> + > >>>>>>> +size_t odp_buffer_segment_count(odp_buffer_t buf) > >>>>>>> +{ > >>>>>>> + odp_buffer_hdr_t *buf_hdr = odp_buf_to_hdr(buf); > >>>>>>> + return (size_t)buf_hdr->scatter.num_bufs + 1; > >>>>>>> +} > >>>>>>> > >>>>>>> int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf) > >>>>>>> { > >>>>>>> @@ -101,8 +116,113 @@ void odp_buffer_print(odp_buffer_t buf) > >>>>>>> printf("\n%s\n", str); > >>>>>>> } > >>>>>>> > >>>>>>> +void *odp_buffer_udata(odp_buffer_t buf, size_t *udata_size) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)udata_size; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> +void *odp_buffer_udata_addr(odp_buffer_t buf) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> +odp_buffer_segment_t odp_buffer_segment_by_index(odp_buffer_t buf, > >>>>>>> + size_t ndx) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)ndx; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> +odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf, > >>>>>>> + odp_buffer_segment_t > seg) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)seg; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> +void *odp_buffer_segment_map(odp_buffer_t buf, > odp_buffer_segment_t > >>>>>>> seg, > >>>>>>> + size_t *seglen) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)seg; > >>>>>>> + (void)seglen; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> +void *odp_buffer_offset_map(odp_buffer_t buf, size_t offset, > >>>>>>> +size_t *seglen) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)offset; > >>>>>>> + (void)seglen; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> +void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)offset; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return; > >>>>>>> +} > >>>>>>> + > >>>>>>> void odp_buffer_copy_scatter(odp_buffer_t buf_dst, odp_buffer_t > >>>>>>> buf_src) > >>>>>>> { > >>>>>>> (void)buf_dst; > >>>>>>> (void)buf_src; > >>>>>>> } > >>>>>>> + > >>>>>>> +odp_buffer_t odp_buffer_split(odp_buffer_t buf, size_t offset) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)offset; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> +odp_buffer_t odp_buffer_join(odp_buffer_t buf1, odp_buffer_t buf2) > >>>>>>> +{ > >>>>>>> + (void)buf1; > >>>>>>> + (void)buf2; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> +odp_buffer_t odp_buffer_trim(odp_buffer_t buf, size_t offset) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)offset; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> +odp_buffer_t odp_buffer_extend(odp_buffer_t buf, size_t ext) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + (void)ext; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> +odp_buffer_t odp_buffer_clone(odp_buffer_t buf) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> +odp_buffer_t odp_buffer_copy(odp_buffer_t buf) > >>>>>>> +{ > >>>>>>> + (void)buf; > >>>>>>> + ODP_UNIMPLEMENTED(); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> + > >>>>>>> diff --git a/platform/linux-generic/odp_buffer_pool.c > >>>>>>> b/platform/linux-generic/odp_buffer_pool.c > >>>>>>> index a48d7d6..bff4db5 100644 > >>>>>>> --- a/platform/linux-generic/odp_buffer_pool.c > >>>>>>> +++ b/platform/linux-generic/odp_buffer_pool.c > >>>>>>> @@ -471,6 +471,13 @@ odp_buffer_t > odp_buffer_alloc(odp_buffer_pool_t > >>>>>>> pool_hdl) > >>>>>>> return handle.u32; > >>>>>>> } > >>>>>>> > >>>>>>> +odp_buffer_t odp_buffer_alloc_size(odp_buffer_pool_t pool, size_t > >>>>>>> size) > >>>>>>> +{ > >>>>>>> + (void)pool; > >>>>>>> + (void) size; > >>>>>>> + ODP_ERR("%s function is yet to be implemented", __func__); > >>>>>>> + return 0; > >>>>>>> +} > >>>>>>> > >>>>>>> void odp_buffer_free(odp_buffer_t buf) > >>>>>>> { > >>>>>>> -- > >>>>>>> 2.0.1.472.g6f92e5f > >>>>>>> > >>>>>>> > >>>>>>> _______________________________________________ > >>>>>>> lng-odp mailing list > >>>>>>> [email protected] > >>>>>>> http://lists.linaro.org/mailman/listinfo/lng-odp > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> _______________________________________________ > >>>>>>> lng-odp mailing list > >>>>>>> [email protected] > >>>>>>> http://lists.linaro.org/mailman/listinfo/lng-odp > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>> > >>>>>> > >>>>>> > >>>>>> _______________________________________________ > >>>>>> lng-odp mailing list > >>>>>> [email protected] > >>>>>> http://lists.linaro.org/mailman/listinfo/lng-odp > >>>>>> > >>>>> > >>>>> > >>>>> _______________________________________________ > >>>>> lng-odp mailing list > >>>>> [email protected] > >>>>> http://lists.linaro.org/mailman/listinfo/lng-odp > >>>>> > >>>> > >>> > >> > >> > >> _______________________________________________ > >> lng-odp mailing list > >> [email protected] > >> http://lists.linaro.org/mailman/listinfo/lng-odp > >> > > _______________________________________________ > lng-odp mailing list > [email protected] > http://lists.linaro.org/mailman/listinfo/lng-odp > > >
_______________________________________________ lng-odp mailing list [email protected] http://lists.linaro.org/mailman/listinfo/lng-odp
