On Fri, Oct 21, 2016 at 12:07 PM, Bala Manoharan <bala.manoha...@linaro.org>
wrote:

> Regards,
> Bala
>
>
> On 21 October 2016 at 19:41, Bill Fischofer <bill.fischo...@linaro.org>
> wrote:
> >
> >
> > On Fri, Oct 21, 2016 at 8:21 AM, Bala Manoharan <
> bala.manoha...@linaro.org>
> > wrote:
> >>
> >> Regards,
> >> Bala
> >>
> >>
> >> On 11 October 2016 at 09:15, Bill Fischofer <bill.fischo...@linaro.org>
> >> wrote:
> >> > Introduce four new APIs that support efficient sharing of portions of
> >> > packets.
> >> >
> >> > odp_packet_splice() creates a reference to a base packet by splicing a
> >> > supplied header packet onto it at a specified offset. If multiple
> >> > splices
> >> > are created then each shares the base packet that was spliced.
> >> >
> >> > odp_packet_ref() creates a reference to a base packet by splicing a
> >> > zero-length header onto it at a specified offset. This allows an
> >> > application to "hold onto" a pointer to a packet so that it will not
> be
> >> > freed until all references to it are freed.
> >> >
> >> > odp_packet_is_a_splice() allows an application to determine whether a
> >> > packet is a splice and if so how many individual packets are contained
> >> > within it.
> >> >
> >> > odp_packet_is_spliced() allows an application to determine whether a
> >> > packet
> >> > has a splice on it and if so how many splices are based on it.
> >> >
> >> > Signed-off-by: Bill Fischofer <bill.fischo...@linaro.org>
> >> > ---
> >> >  include/odp/api/spec/packet.h | 103
> >> > ++++++++++++++++++++++++++++++++++++++++++
> >> >  1 file changed, 103 insertions(+)
> >> >
> >> > diff --git a/include/odp/api/spec/packet.h
> >> > b/include/odp/api/spec/packet.h
> >> > index 4a14f2d..8e147a3 100644
> >> > --- a/include/odp/api/spec/packet.h
> >> > +++ b/include/odp/api/spec/packet.h
> >> > @@ -844,6 +844,109 @@ int odp_packet_concat(odp_packet_t *dst,
> >> > odp_packet_t src);
> >> >   */
> >> >  int odp_packet_split(odp_packet_t *pkt, uint32_t len, odp_packet_t
> >> > *tail);
> >> >
> >> > +/**
> >> > + * Splice a packet
> >> > + *
> >> > + * Create a new packet by splicing a header onto an existing packet.
> >> > The
> >> > + * spliced packet consists of the header followed by a shared
> reference
> >> > to the
> >> > + * base packet receiving the splice starting at a designated offset.
> If
> >> > + * multiple splices are created on the same base packet, it is the
> >> > + * application's responsibility to coordinate any changes to the
> shared
> >> > + * segment(s) of the splice, otherwise results are undefined.
> >> > + *
> >> > + * @param hdr    Handle of the header packet to be spliced onto the
> >> > base packet
> >> > + *
> >> > + * @param pkt    Handle of the base packet that is to receive the
> >> > splice
> >> > + *
> >> > + * @param offset Byte offset within the base packet at which the
> splice
> >> > is
> >> > + *               to be made.
> >> > + *
> >> > + * @return       Handle of the spliced packet. This may or may not be
> >> > the
> >> > + *               same as the input hdr packet. The caller should use
> >> > this
> >> > + *               for any future references to the splice. The
> original
> >> > hdr
> >> > + *               packet no longer has any independent existence.
> >> > + *
> >> > + * @retval ODP_PACKET_INVALID If the splice failed. In this case both
> >> > hdr
> >> > + *                            and pkt are unchanged.
> >> > + *
> >> > + * @note The base pkt remains valid after the completion of the
> splice,
> >> > + *       however changes that affect its length may yield
> unpredictable
> >> > + *       results when viewed through the returned splice handle. For
> >> > best
> >> > + *       portability and predictable behavior, applications should
> >> > regard the
> >> > + *       base packet as read only following a successful splice, with
> >> > the
> >> > + *       exception of tailroom manipulation (which still requires
> >> > application
> >> > + *       coordination if multiple splices exist on the same base
> packet
> >> > whose
> >> > + *       tail is being pushed or pulled).
> >> > + *
> >> > + * @note Either packet input to this routine may itself be a splice,
> >> > however
> >> > + *       individual implementations may impose limits on how deeply
> >> > splices
> >> > + *       may be nested and fail the attempted splice if those limits
> >> > are
> >> > + *       exceeded.
> >> > + *
> >> > + * @note The packets used to create a splice may reside in different
> >> > pools,
> >> > + *       however individual implementations may require that both
> >> > reside in
> >> > + *       the same pool and fail the attempted splice if this
> >> > restriction is
> >> > + *       not observed. Upon return odp_packet_pool() returns the pool
> >> > id of
> >> > + *       the header packet.
> >> > + *
> >> > + * @note Once successfully spliced, the base packet may be freed via
> >> > + *       odp_packet_free(), however the storage used to represent it
> >> > will not
> >> > + *       be released until all splices based on it have themselves
> been
> >> > freed.
> >>
> >> Do you have a reason why the 'base' packet will be freed by the
> >> application after creating the slice?
> >
> >
> > The point being made here is only that the storage behind the base packet
> > will not be released until all references to it are freed. The
> application
> > is under no obligation to issue an odp_packet_free() at any particular
> time.
> > One reason why a packet (or one of its references) may be freed is if it
> is
> > transmitted since ODP TX processing implicitly calls odp_packet_free()
> once
> > the odp_packet_t has been sent. So, for example, if a reference to a
> packet
> > is transmitted then the base packet will still be around since only the
> > reference will be freed by the transmit. Or conversely if a packet is
> > transmitted but the caller still holds a reference to it then again while
> > the base packet will be freed by the transmit the portion of it
> contained in
> > the reference would still be retained until the reference was itself
> freed.
>
> I believe this is a general concept with reference, whenever you do
> not want a packet to be freed during transmission you create a
> reference for the packet and then transmit the packet so that the
> implementation only decrements the reference count but does not free
> the packet.
> So I would prefer changing the sentence to reflect the general concept
> of reference book keeping rather than explaining about storage of the
> base packet, since the concept is same for 'base' packet or a whole
> packet and the way it gets implemented is implementation specific.
>

I have no problem rewording this as the concept remains the same. We don't
mention reference counts explicitly, though that's the obvious way for
implementations to do the necessary bookkeeping.


>
> >
> >>
> >>
> >> > + */
> >> > +odp_packet_t odp_packet_splice(odp_packet_t hdr,
> >> > +                              odp_packet_t pkt, uint32_t offset);
> >>
> >> Do we have an use-case for this scenario?
> >> I would prefer that the API take the entire second packet instead of
> >> an 'offset' at-least in the first version and that the 'hdr' handle
> >> becomes invalid once the packet has been sliced and the new handle
> >> returned replaces the 'hdr' handle.
> >
> >
> > The main use case here would be to splice on a preallocated header onto a
> > portion of a base packet representing the payload.  The alternative
> would be
> > to create a reference (e.g., splice a zero-length header onto a packet)
> and
> > then call odp_packet_push_head() to build a header onto the reference.
> But
> > being able to have these headers preallocated could be more efficient.
> >
> > As currently defined, the returned handle replaces the hdr packet handle
> > since the hdr no longer has an independent identity after the splice. The
> > base pkt, by contrast, is still valid since other references/splices can
> be
> > created on it to result in sharing. So the second part of your request is
> > already handled. I tried to make that clear in the doxygen for @return.
>
> This could be achieved by first creating reference for the hdr packet
> and then using the handle returned by the reference API and create a
> splice.
>

That's effectively what happens as a reference is just a splice of a
zero-length header packet. Creating a reference to the header would mean
that the header would then have to be regarded as read-only, however.
Splicing that onto a base would then create a compound reference (you're
splicing a reference/splice onto another packet). odp-linux can do that but
the question is whether every implementation can do arbitrary compound
splices? That may need to be another capability indication.


>
> >
> > Restricting the valid offset values for a splice is something that may be
> > needed for some implementations, and that's why I wanted to have this
> > discussion. I'd expect such limits to be communicated in an
> > odp_packet_capability() API that we'd add.
>
> I believe offset is something which could be implemented by all HWs
> using software interaction but since these APIs are executed in the
> fast-path having a separate API for creating reference at 0 offset
> could be beneficial as the implementation could be more efficient in
> that case.
>

Petri originally proposed one API and I proposed to split that into two so
that references didn't have to specify an explicit null header. Having a
third that doesn't use the offset parameter is a possibility, but
specifying an offset of 0 seems simple to optimize. But I'm certainly open
to having that as a separate API if that makes life easier.


>
> >
> > Of course, if a given implementation can only support splicing at offset
> > zero then a non-zero offset splice can be affected by first calling
> > odp_packet_pull_head() on the base packet before doing the splice. I
> assume
> > that you can support that combination of operations?
> >
> >>
> >>
> >> > +
> >> > +/**
> >> > + * Create a reference to a packet
> >> > + *
> >> > + * Create a (shared) reference to a base packet starting at a
> specified
> >> > + * byte offset. A reference is simply a splice with a zero-length
> >> > header.
> >> > + *
> >> > + * @param pkt    Handle of the base packet for which a reference is
> to
> >> > be
> >> > + *               created.
> >> > + * @param offset Byte offset in the base packet at which shared
> >> > reference is
> >> > + *               to begin.
> >> > + *
> >> > + * @return                    Handle of the reference packet
> >> > + * @retval ODP_PACKET_INVALID Operation failed. Base packet remains
> >> > unchanged.
> >> > + *
> >> > + * @note The zero-length header used to create a packet reference is
> >> > always
> >> > + *       drawn from the same pool as the base packet.
> >> > + *
> >> > + * @note Because references are a type of splice, any bytes pushed
> onto
> >> > the
> >> > + *       head of a reference (via odp_packet_push_head() or
> >> > + *       odp_packet_extend_head() are unique to this reference and
> are
> >> > not
> >> > + *       seen by any other reference to the same base packet.
> >> > + */
> >> > +odp_packet_t odp_packet_ref(odp_packet_t pkt, uint32_t offset);
> >>
> >> In the first version we can drop the offset and create a reference of
> >> the entire packet.
> >
> >
> > Since a reference is just a splice of a zero-length header any
> restriction
> > on supported splice offsets would propagate to references as well. Can
> this
> > be done via a capability() API? The advantage of keeping the offset
> (even if
> > 0 is the only valid value in the first release) is to preserve API/ABI
> > compatibility if this restriction is relaxed in a later release.
>
> I believe the offset 0 will be the general use-case hence it is better
> to keep a separate API for creating reference of entire packet.
> Creating multiple references at multiple offset of a packet
> complicates the implementation logic and since these codes execute in
> the fast path the logic should be as efficient as possible.
>
> I would prefer adding the simple use-case in this version since I
> believe it could be easily agreed upon and implemented by all HWs.
>

I'd like to get confirmation of that from other HW platforms. Good to have
your input on this.


> >
> >>
> >>
> >> > +
> >> > +/**
> >> > + * Tests if a packet is a splice
> >> > + *
> >> > + * A packet is a splice if it was created by odp_packet_splice() or
> >> > + * odp_packet_ref(). Note that a splice may be a simple splice or a
> >> > + * compound splice (a splice created from another splice).
> >> > + *
> >> > + * @param pkt Packet Handle
> >> > + *
> >> > + * @retval 0 Packet is not a splice
> >> > + * @retval >0 Packet is a splice containing N individual packets
> >> > + */
> >> > +int odp_packet_is_a_splice(odp_packet_t pkt);
> >> > +
> >> > +/**
> >> > + * Tests if a packet is spliced
> >> > + *
> >> > + * A packet is spliced if a splice was created on it by
> >> > odp_packet_splice()
> >> > + * or odp_packet_ref().
> >> > + *
> >> > + * @param pkt Packet Handle
> >> > + *
> >> > + * @retval 0 Packet is not spliced
> >> > + * @retval >0 Packet has N splices based on it
> >> > + */
> >> > +int odp_packet_is_spliced(odp_packet_t pkt);
> >> > +
> >> >  /*
> >> >   *
> >> >   * Copy
> >> > --
> >> > 2.7.4
> >> >
> >
> >
>

Reply via email to