diff mbox

[v2,5/5] linux-generic: packet: initialize only selected odp_packet_hdr_t members

Message ID 1463392220-22856-6-git-send-email-matias.elo@nokia.com
State Accepted
Commit f2ed9070247b53110d18fef193867c86085a2d89
Headers show

Commit Message

Elo, Matias (Nokia - FI/Espoo) May 16, 2016, 9:50 a.m. UTC
Using memset to initialize struct odp_packet_hdr_t contents
to 0 has a significant overhead. Instead, initialize only
the required members of the struct.

Signed-off-by: Matias Elo <matias.elo@nokia.com>
---
 platform/linux-generic/include/odp_packet_internal.h | 13 +++++++++----
 platform/linux-generic/odp_packet.c                  | 18 ++++++------------
 2 files changed, 15 insertions(+), 16 deletions(-)

Comments

Mike Holmes May 16, 2016, 2:25 p.m. UTC | #1
On 16 May 2016 at 05:50, Matias Elo <matias.elo@nokia.com> wrote:

> Using memset to initialize struct odp_packet_hdr_t contents
> to 0 has a significant overhead. Instead, initialize only
> the required members of the struct.
>
> Signed-off-by: Matias Elo <matias.elo@nokia.com>
> ---
>  platform/linux-generic/include/odp_packet_internal.h | 13 +++++++++----
>  platform/linux-generic/odp_packet.c                  | 18
> ++++++------------
>  2 files changed, 15 insertions(+), 16 deletions(-)
>
> diff --git a/platform/linux-generic/include/odp_packet_internal.h
> b/platform/linux-generic/include/odp_packet_internal.h
> index 1306b05..c87bc9f 100644
> --- a/platform/linux-generic/include/odp_packet_internal.h
> +++ b/platform/linux-generic/include/odp_packet_internal.h
> @@ -4,7 +4,6 @@
>   * SPDX-License-Identifier:     BSD-3-Clause
>   */
>
-
>  /**
>   * @file
>   *
> @@ -129,11 +128,16 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) ==
> sizeof(uint32_t),
>
>  /**
>   * Internal Packet header
> + *
> + * To optimize fast path performance this struct is not initialized to
> zero in
> + * packet_init(). Because of this any new fields added must be reviewed
> for
> + * initialization requirements.
>   */


This file will not contribute to the generated API documentation and I
think it should. This platform specific warning should appear there as a
doxygen  @warning
Perhaps we need to start a trend of adding a doxygen platform specific
module called "PLATFORM SPECIFICS", then we can add information with the
@addtogroup platform_specifics and users across platforms will know where
to look for this sort of information.

 typedef struct {
>         /* common buffer header */
>         odp_buffer_hdr_t buf_hdr;
>
> +       /* Following members are initialized by packet_init() */
>         input_flags_t  input_flags;
>         error_flags_t  error_flags;
>         output_flags_t output_flags;
> @@ -142,15 +146,16 @@ typedef struct {
>         uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */
>         uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also
> ICMP) */
>
> -       uint32_t l3_len;         /**< Layer 3 length */
> -       uint32_t l4_len;         /**< Layer 4 length */
> -
>         uint32_t frame_len;
>         uint32_t headroom;
>         uint32_t tailroom;
>
>         odp_pktio_t input;
>
> +       /* Members below are not initialized by packet_init() */
> +       uint32_t l3_len;         /**< Layer 3 length */
> +       uint32_t l4_len;         /**< Layer 4 length */
> +
>         uint32_t flow_hash;      /**< Flow hash value */
>         odp_time_t timestamp;    /**< Timestamp value */
>
> diff --git a/platform/linux-generic/odp_packet.c
> b/platform/linux-generic/odp_packet.c
> index 4f523c9..8dde404 100644
> --- a/platform/linux-generic/odp_packet.c
> +++ b/platform/linux-generic/odp_packet.c
> @@ -49,19 +49,11 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
>  static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
>                         size_t size, int parse)
>  {
> -       /*
> -       * Reset parser metadata.  Note that we clear via memset to make
> -       * this routine indepenent of any additional adds to packet
> metadata.
> -       */
> -       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
> buf_hdr);
> -       uint8_t *start;
> -       size_t len;
> +       pkt_hdr->input_flags.all  = 0;
> +       pkt_hdr->output_flags.all = 0;
> +       pkt_hdr->error_flags.all  = 0;
>
> -       start = (uint8_t *)pkt_hdr + start_offset;
> -       len = sizeof(odp_packet_hdr_t) - start_offset;
> -       memset(start, 0, len);
> -
> -       /* Set metadata items that initialize to non-zero values */
> +       pkt_hdr->l2_offset = 0;
>         pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
>         pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
>
> @@ -79,6 +71,8 @@ static void packet_init(pool_entry_t *pool,
> odp_packet_hdr_t *pkt_hdr,
>         pkt_hdr->tailroom  =
>                 (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
>                 (pool->s.headroom + size);
> +
> +       pkt_hdr->input = ODP_PKTIO_INVALID;
>  }
>
>  odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse)
> --
> 1.9.1
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
Bill Fischofer May 16, 2016, 10:52 p.m. UTC | #2
On Mon, May 16, 2016 at 9:25 AM, Mike Holmes <mike.holmes@linaro.org> wrote:

> On 16 May 2016 at 05:50, Matias Elo <matias.elo@nokia.com> wrote:
>
> > Using memset to initialize struct odp_packet_hdr_t contents
> > to 0 has a significant overhead. Instead, initialize only
> > the required members of the struct.
> >
> > Signed-off-by: Matias Elo <matias.elo@nokia.com>
> > ---
> >  platform/linux-generic/include/odp_packet_internal.h | 13 +++++++++----
> >  platform/linux-generic/odp_packet.c                  | 18
> > ++++++------------
> >  2 files changed, 15 insertions(+), 16 deletions(-)
> >
> > diff --git a/platform/linux-generic/include/odp_packet_internal.h
> > b/platform/linux-generic/include/odp_packet_internal.h
> > index 1306b05..c87bc9f 100644
> > --- a/platform/linux-generic/include/odp_packet_internal.h
> > +++ b/platform/linux-generic/include/odp_packet_internal.h
> > @@ -4,7 +4,6 @@
> >   * SPDX-License-Identifier:     BSD-3-Clause
> >   */
> >
> -
> >  /**
> >   * @file
> >   *
> > @@ -129,11 +128,16 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) ==
> > sizeof(uint32_t),
> >
> >  /**
> >   * Internal Packet header
> > + *
> > + * To optimize fast path performance this struct is not initialized to
> > zero in
> > + * packet_init(). Because of this any new fields added must be reviewed
> > for
> > + * initialization requirements.
> >   */
>
>
> This file will not contribute to the generated API documentation and I
>

It's not relevant to the API, only to the odp-linux implementation of the
API.


> think it should. This platform specific warning should appear there as a
> doxygen  @warning
> Perhaps we need to start a trend of adding a doxygen platform specific
> module called "PLATFORM SPECIFICS", then we can add information with the
> @addtogroup platform_specifics and users across platforms will know where
> to look for this sort of information.


The best place for this sort of implementation documentation is in the
comments in the C code itself. We just want a reminder to future
maintainers of the code of a shortcut that was taken for performance
reasons and the cautions that need to be observed as a result.

If we want to have these sort of notes be collated as part of a
"Maintainer's Guide" for odp-linux, that would seem a worthwhile project.
Something to consider adding for Tiger Moth?


>
>  typedef struct {
> >         /* common buffer header */
> >         odp_buffer_hdr_t buf_hdr;
> >
> > +       /* Following members are initialized by packet_init() */
> >         input_flags_t  input_flags;
> >         error_flags_t  error_flags;
> >         output_flags_t output_flags;
> > @@ -142,15 +146,16 @@ typedef struct {
> >         uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */
> >         uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also
> > ICMP) */
> >
> > -       uint32_t l3_len;         /**< Layer 3 length */
> > -       uint32_t l4_len;         /**< Layer 4 length */
> > -
> >         uint32_t frame_len;
> >         uint32_t headroom;
> >         uint32_t tailroom;
> >
> >         odp_pktio_t input;
> >
> > +       /* Members below are not initialized by packet_init() */
> > +       uint32_t l3_len;         /**< Layer 3 length */
> > +       uint32_t l4_len;         /**< Layer 4 length */
> > +
> >         uint32_t flow_hash;      /**< Flow hash value */
> >         odp_time_t timestamp;    /**< Timestamp value */
> >
> > diff --git a/platform/linux-generic/odp_packet.c
> > b/platform/linux-generic/odp_packet.c
> > index 4f523c9..8dde404 100644
> > --- a/platform/linux-generic/odp_packet.c
> > +++ b/platform/linux-generic/odp_packet.c
> > @@ -49,19 +49,11 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
> >  static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
> >                         size_t size, int parse)
> >  {
> > -       /*
> > -       * Reset parser metadata.  Note that we clear via memset to make
> > -       * this routine indepenent of any additional adds to packet
> > metadata.
> > -       */
> > -       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
> > buf_hdr);
> > -       uint8_t *start;
> > -       size_t len;
> > +       pkt_hdr->input_flags.all  = 0;
> > +       pkt_hdr->output_flags.all = 0;
> > +       pkt_hdr->error_flags.all  = 0;
> >
> > -       start = (uint8_t *)pkt_hdr + start_offset;
> > -       len = sizeof(odp_packet_hdr_t) - start_offset;
> > -       memset(start, 0, len);
> > -
> > -       /* Set metadata items that initialize to non-zero values */
> > +       pkt_hdr->l2_offset = 0;
> >         pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
> >         pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
> >
> > @@ -79,6 +71,8 @@ static void packet_init(pool_entry_t *pool,
> > odp_packet_hdr_t *pkt_hdr,
> >         pkt_hdr->tailroom  =
> >                 (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
> >                 (pool->s.headroom + size);
> > +
> > +       pkt_hdr->input = ODP_PKTIO_INVALID;
> >  }
> >
> >  odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse)
> > --
> > 1.9.1
> >
> > _______________________________________________
> > lng-odp mailing list
> > lng-odp@lists.linaro.org
> > https://lists.linaro.org/mailman/listinfo/lng-odp
> >
>
>
>
> --
> Mike Holmes
> Technical Manager - Linaro Networking Group
> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
> "Work should be fun and collaborative, the rest follows"
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
Mike Holmes May 17, 2016, 5:42 p.m. UTC | #3
On 16 May 2016 at 18:52, Bill Fischofer <bill.fischofer@linaro.org> wrote:

>
>
> On Mon, May 16, 2016 at 9:25 AM, Mike Holmes <mike.holmes@linaro.org>
> wrote:
>
>> On 16 May 2016 at 05:50, Matias Elo <matias.elo@nokia.com> wrote:
>>
>> > Using memset to initialize struct odp_packet_hdr_t contents
>> > to 0 has a significant overhead. Instead, initialize only
>> > the required members of the struct.
>> >
>> > Signed-off-by: Matias Elo <matias.elo@nokia.com>
>> > ---
>> >  platform/linux-generic/include/odp_packet_internal.h | 13 +++++++++----
>> >  platform/linux-generic/odp_packet.c                  | 18
>> > ++++++------------
>> >  2 files changed, 15 insertions(+), 16 deletions(-)
>> >
>> > diff --git a/platform/linux-generic/include/odp_packet_internal.h
>> > b/platform/linux-generic/include/odp_packet_internal.h
>> > index 1306b05..c87bc9f 100644
>> > --- a/platform/linux-generic/include/odp_packet_internal.h
>> > +++ b/platform/linux-generic/include/odp_packet_internal.h
>> > @@ -4,7 +4,6 @@
>> >   * SPDX-License-Identifier:     BSD-3-Clause
>> >   */
>> >
>> -
>> >  /**
>> >   * @file
>> >   *
>> > @@ -129,11 +128,16 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) ==
>> > sizeof(uint32_t),
>> >
>> >  /**
>> >   * Internal Packet header
>> > + *
>> > + * To optimize fast path performance this struct is not initialized to
>> > zero in
>> > + * packet_init(). Because of this any new fields added must be reviewed
>> > for
>> > + * initialization requirements.
>> >   */
>>
>>
>> This file will not contribute to the generated API documentation and I
>>
>
> It's not relevant to the API, only to the odp-linux implementation of the
> API.
>

Exactly, as a user of the odp-linux implementation dont I want to know that
some fields are not set ?


>
>
>> think it should. This platform specific warning should appear there as a
>> doxygen  @warning
>> Perhaps we need to start a trend of adding a doxygen platform specific
>> module called "PLATFORM SPECIFICS", then we can add information with the
>> @addtogroup platform_specifics and users across platforms will know where
>> to look for this sort of information.
>
>
> The best place for this sort of implementation documentation is in the
> comments in the C code itself. We just want a reminder to future
> maintainers of the code of a shortcut that was taken for performance
> reasons and the cautions that need to be observed as a result.
>

I dont agree, too many implementations copy this code, they need to be
aware that a normal assumption is broken when they build upon it in their
implementation.


>
> If we want to have these sort of notes be collated as part of a
> "Maintainer's Guide" for odp-linux, that would seem a worthwhile project.
> Something to consider adding for Tiger Moth?
>

I think it has to be in the implementer's guide since implementers often
use odp-linux as the starting point, we need to warn them. It also has to
be in the API guide if these structs will be seen by an application.

I think it needs to happen before Monarch since this behaviour is
unexpected and we need to make sure it is noticed as the other
implementations home in on a fully compliant Monarch API



>
>
>>
>>  typedef struct {
>> >         /* common buffer header */
>> >         odp_buffer_hdr_t buf_hdr;
>> >
>> > +       /* Following members are initialized by packet_init() */
>> >         input_flags_t  input_flags;
>> >         error_flags_t  error_flags;
>> >         output_flags_t output_flags;
>> > @@ -142,15 +146,16 @@ typedef struct {
>> >         uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */
>> >         uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also
>> > ICMP) */
>> >
>> > -       uint32_t l3_len;         /**< Layer 3 length */
>> > -       uint32_t l4_len;         /**< Layer 4 length */
>> > -
>> >         uint32_t frame_len;
>> >         uint32_t headroom;
>> >         uint32_t tailroom;
>> >
>> >         odp_pktio_t input;
>> >
>> > +       /* Members below are not initialized by packet_init() */
>> > +       uint32_t l3_len;         /**< Layer 3 length */
>> > +       uint32_t l4_len;         /**< Layer 4 length */
>> > +
>> >         uint32_t flow_hash;      /**< Flow hash value */
>> >         odp_time_t timestamp;    /**< Timestamp value */
>> >
>> > diff --git a/platform/linux-generic/odp_packet.c
>> > b/platform/linux-generic/odp_packet.c
>> > index 4f523c9..8dde404 100644
>> > --- a/platform/linux-generic/odp_packet.c
>> > +++ b/platform/linux-generic/odp_packet.c
>> > @@ -49,19 +49,11 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
>> >  static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
>> >                         size_t size, int parse)
>> >  {
>> > -       /*
>> > -       * Reset parser metadata.  Note that we clear via memset to make
>> > -       * this routine indepenent of any additional adds to packet
>> > metadata.
>> > -       */
>> > -       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>> > buf_hdr);
>> > -       uint8_t *start;
>> > -       size_t len;
>> > +       pkt_hdr->input_flags.all  = 0;
>> > +       pkt_hdr->output_flags.all = 0;
>> > +       pkt_hdr->error_flags.all  = 0;
>> >
>> > -       start = (uint8_t *)pkt_hdr + start_offset;
>> > -       len = sizeof(odp_packet_hdr_t) - start_offset;
>> > -       memset(start, 0, len);
>> > -
>> > -       /* Set metadata items that initialize to non-zero values */
>> > +       pkt_hdr->l2_offset = 0;
>> >         pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
>> >         pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
>> >
>> > @@ -79,6 +71,8 @@ static void packet_init(pool_entry_t *pool,
>> > odp_packet_hdr_t *pkt_hdr,
>> >         pkt_hdr->tailroom  =
>> >                 (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
>> >                 (pool->s.headroom + size);
>> > +
>> > +       pkt_hdr->input = ODP_PKTIO_INVALID;
>> >  }
>> >
>> >  odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse)
>> > --
>> > 1.9.1
>> >
>> > _______________________________________________
>> > lng-odp mailing list
>> > lng-odp@lists.linaro.org
>> > https://lists.linaro.org/mailman/listinfo/lng-odp
>> >
>>
>>
>>
>> --
>> Mike Holmes
>> Technical Manager - Linaro Networking Group
>> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
>> "Work should be fun and collaborative, the rest follows"
>> _______________________________________________
>> lng-odp mailing list
>> lng-odp@lists.linaro.org
>> https://lists.linaro.org/mailman/listinfo/lng-odp
>>
>
>
Bill Fischofer May 17, 2016, 6:46 p.m. UTC | #4
On Tue, May 17, 2016 at 12:42 PM, Mike Holmes <mike.holmes@linaro.org>
wrote:

>
>
> On 16 May 2016 at 18:52, Bill Fischofer <bill.fischofer@linaro.org> wrote:
>
>>
>>
>> On Mon, May 16, 2016 at 9:25 AM, Mike Holmes <mike.holmes@linaro.org>
>> wrote:
>>
>>> On 16 May 2016 at 05:50, Matias Elo <matias.elo@nokia.com> wrote:
>>>
>>> > Using memset to initialize struct odp_packet_hdr_t contents
>>> > to 0 has a significant overhead. Instead, initialize only
>>> > the required members of the struct.
>>> >
>>> > Signed-off-by: Matias Elo <matias.elo@nokia.com>
>>> > ---
>>> >  platform/linux-generic/include/odp_packet_internal.h | 13
>>> +++++++++----
>>> >  platform/linux-generic/odp_packet.c                  | 18
>>> > ++++++------------
>>> >  2 files changed, 15 insertions(+), 16 deletions(-)
>>> >
>>> > diff --git a/platform/linux-generic/include/odp_packet_internal.h
>>> > b/platform/linux-generic/include/odp_packet_internal.h
>>> > index 1306b05..c87bc9f 100644
>>> > --- a/platform/linux-generic/include/odp_packet_internal.h
>>> > +++ b/platform/linux-generic/include/odp_packet_internal.h
>>> > @@ -4,7 +4,6 @@
>>> >   * SPDX-License-Identifier:     BSD-3-Clause
>>> >   */
>>> >
>>> -
>>> >  /**
>>> >   * @file
>>> >   *
>>> > @@ -129,11 +128,16 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) ==
>>> > sizeof(uint32_t),
>>> >
>>> >  /**
>>> >   * Internal Packet header
>>> > + *
>>> > + * To optimize fast path performance this struct is not initialized to
>>> > zero in
>>> > + * packet_init(). Because of this any new fields added must be
>>> reviewed
>>> > for
>>> > + * initialization requirements.
>>> >   */
>>>
>>>
>>> This file will not contribute to the generated API documentation and I
>>>
>>
>> It's not relevant to the API, only to the odp-linux implementation of the
>> API.
>>
>
> Exactly, as a user of the odp-linux implementation dont I want to know
> that some fields are not set ?
>

No, because the internals of odp-linux (or any other implementation) are
not visible to users. The only thing users see is what the API exposes.
These optimizations have no impact on the API. The only people who care
about this are the maintainers of odp-linux.


>
>>
>>
>>> think it should. This platform specific warning should appear there as a
>>> doxygen  @warning
>>> Perhaps we need to start a trend of adding a doxygen platform specific
>>> module called "PLATFORM SPECIFICS", then we can add information with the
>>> @addtogroup platform_specifics and users across platforms will know where
>>> to look for this sort of information.
>>
>>
>> The best place for this sort of implementation documentation is in the
>> comments in the C code itself. We just want a reminder to future
>> maintainers of the code of a shortcut that was taken for performance
>> reasons and the cautions that need to be observed as a result.
>>
>
> I dont agree, too many implementations copy this code, they need to be
> aware that a normal assumption is broken when they build upon it in their
> implementation.
>

Blindly copying code is never a good idea. However, if you copy it its
function is unchanged, so that has no effect. The only way you get in
trouble is by copying and then changing other things without understanding
what you're doing. That's always a recipe for trouble.


>
>
>>
>> If we want to have these sort of notes be collated as part of a
>> "Maintainer's Guide" for odp-linux, that would seem a worthwhile project.
>> Something to consider adding for Tiger Moth?
>>
>
> I think it has to be in the implementer's guide since implementers often
> use odp-linux as the starting point, we need to warn them. It also has to
> be in the API guide if these structs will be seen by an application.
>
> I think it needs to happen before Monarch since this behaviour is
> unexpected and we need to make sure it is noticed as the other
> implementations home in on a fully compliant Monarch API
>
>
Again, the fields that this patch deletes were never exposed as part of any
ODP API. They were positioning for future extensions which never
materialized. If they do (via new APIs) then they will be added back as
needed. There's nothing nefarious going on here. The only change is that
before you could add a new field and be somewhat sloppy about it. Now you
have to think about what you're doing.


>
>
>>
>>
>>>
>>>  typedef struct {
>>> >         /* common buffer header */
>>> >         odp_buffer_hdr_t buf_hdr;
>>> >
>>> > +       /* Following members are initialized by packet_init() */
>>> >         input_flags_t  input_flags;
>>> >         error_flags_t  error_flags;
>>> >         output_flags_t output_flags;
>>> > @@ -142,15 +146,16 @@ typedef struct {
>>> >         uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */
>>> >         uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also
>>> > ICMP) */
>>> >
>>> > -       uint32_t l3_len;         /**< Layer 3 length */
>>> > -       uint32_t l4_len;         /**< Layer 4 length */
>>> > -
>>> >         uint32_t frame_len;
>>> >         uint32_t headroom;
>>> >         uint32_t tailroom;
>>> >
>>> >         odp_pktio_t input;
>>> >
>>> > +       /* Members below are not initialized by packet_init() */
>>> > +       uint32_t l3_len;         /**< Layer 3 length */
>>> > +       uint32_t l4_len;         /**< Layer 4 length */
>>> > +
>>> >         uint32_t flow_hash;      /**< Flow hash value */
>>> >         odp_time_t timestamp;    /**< Timestamp value */
>>> >
>>> > diff --git a/platform/linux-generic/odp_packet.c
>>> > b/platform/linux-generic/odp_packet.c
>>> > index 4f523c9..8dde404 100644
>>> > --- a/platform/linux-generic/odp_packet.c
>>> > +++ b/platform/linux-generic/odp_packet.c
>>> > @@ -49,19 +49,11 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
>>> >  static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
>>> >                         size_t size, int parse)
>>> >  {
>>> > -       /*
>>> > -       * Reset parser metadata.  Note that we clear via memset to make
>>> > -       * this routine indepenent of any additional adds to packet
>>> > metadata.
>>> > -       */
>>> > -       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>>> > buf_hdr);
>>> > -       uint8_t *start;
>>> > -       size_t len;
>>> > +       pkt_hdr->input_flags.all  = 0;
>>> > +       pkt_hdr->output_flags.all = 0;
>>> > +       pkt_hdr->error_flags.all  = 0;
>>> >
>>> > -       start = (uint8_t *)pkt_hdr + start_offset;
>>> > -       len = sizeof(odp_packet_hdr_t) - start_offset;
>>> > -       memset(start, 0, len);
>>> > -
>>> > -       /* Set metadata items that initialize to non-zero values */
>>> > +       pkt_hdr->l2_offset = 0;
>>> >         pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
>>> >         pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
>>> >
>>> > @@ -79,6 +71,8 @@ static void packet_init(pool_entry_t *pool,
>>> > odp_packet_hdr_t *pkt_hdr,
>>> >         pkt_hdr->tailroom  =
>>> >                 (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
>>> >                 (pool->s.headroom + size);
>>> > +
>>> > +       pkt_hdr->input = ODP_PKTIO_INVALID;
>>> >  }
>>> >
>>> >  odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int
>>> parse)
>>> > --
>>> > 1.9.1
>>> >
>>> > _______________________________________________
>>> > lng-odp mailing list
>>> > lng-odp@lists.linaro.org
>>> > https://lists.linaro.org/mailman/listinfo/lng-odp
>>> >
>>>
>>>
>>>
>>> --
>>> Mike Holmes
>>> Technical Manager - Linaro Networking Group
>>> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM
>>> SoCs
>>> "Work should be fun and collaborative, the rest follows"
>>> _______________________________________________
>>> lng-odp mailing list
>>> lng-odp@lists.linaro.org
>>> https://lists.linaro.org/mailman/listinfo/lng-odp
>>>
>>
>>
>
>
> --
> Mike Holmes
> Technical Manager - Linaro Networking Group
> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
> "Work should be fun and collaborative, the rest follows"
>
>
>
Mike Holmes May 18, 2016, 5:31 p.m. UTC | #5
On 18 May 2016 at 02:17, Elo, Matias (Nokia - FI/Espoo) <
matias.elo@nokia.com> wrote:

>
>
>
>
> *From:* Bill Fischofer [mailto:bill.fischofer@linaro.org]
> *Sent:* Tuesday, May 17, 2016 9:46 PM
> *To:* Mike Holmes <mike.holmes@linaro.org>
> *Cc:* Elo, Matias (Nokia - FI/Espoo) <matias.elo@nokia.com>; lng-odp <
> lng-odp@lists.linaro.org>
> *Subject:* Re: [lng-odp] [PATCH v2 5/5] linux-generic: packet: initialize
> only selected odp_packet_hdr_t members
>
>
>
>
>
>
>
> On Tue, May 17, 2016 at 12:42 PM, Mike Holmes <mike.holmes@linaro.org>
> wrote:
>
>
>
>
>
> On 16 May 2016 at 18:52, Bill Fischofer <bill.fischofer@linaro.org> wrote:
>
>
>
>
>
> On Mon, May 16, 2016 at 9:25 AM, Mike Holmes <mike.holmes@linaro.org>
> wrote:
>
> On 16 May 2016 at 05:50, Matias Elo <matias.elo@nokia.com> wrote:
>
> > Using memset to initialize struct odp_packet_hdr_t contents
> > to 0 has a significant overhead. Instead, initialize only
> > the required members of the struct.
> >
> > Signed-off-by: Matias Elo <matias.elo@nokia.com>
> > ---
> >  platform/linux-generic/include/odp_packet_internal.h | 13 +++++++++----
> >  platform/linux-generic/odp_packet.c                  | 18
> > ++++++------------
> >  2 files changed, 15 insertions(+), 16 deletions(-)
> >
> > diff --git a/platform/linux-generic/include/odp_packet_internal.h
> > b/platform/linux-generic/include/odp_packet_internal.h
> > index 1306b05..c87bc9f 100644
> > --- a/platform/linux-generic/include/odp_packet_internal.h
> > +++ b/platform/linux-generic/include/odp_packet_internal.h
> > @@ -4,7 +4,6 @@
> >   * SPDX-License-Identifier:     BSD-3-Clause
> >   */
> >
> -
> >  /**
> >   * @file
> >   *
> > @@ -129,11 +128,16 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) ==
> > sizeof(uint32_t),
> >
> >  /**
> >   * Internal Packet header
> > + *
> > + * To optimize fast path performance this struct is not initialized to
> > zero in
> > + * packet_init(). Because of this any new fields added must be reviewed
> > for
> > + * initialization requirements.
> >   */
>
> This file will not contribute to the generated API documentation and I
>
>
>
> It's not relevant to the API, only to the odp-linux implementation of the
> API.
>
>
>
> Exactly, as a user of the odp-linux implementation dont I want to know
> that some fields are not set ?
>
>
>
> No, because the internals of odp-linux (or any other implementation) are
> not visible to users. The only thing users see is what the API exposes.
> These optimizations have no impact on the API. The only people who care
> about this are the maintainers of odp-linux.
>
>
>
> This is exactly what was done here. Either the uninitialized members are
> not visible to the user at all (op_result, l3_len, l4_len) or the input
> flags are used the check if the values are valid (flow_hash, timetamp).
>
>
I am clearly missing something, I will leave it that I dont think we make
it clear enough to any reusers and our own implementers becasue that /**
doxygen comment is not published anywhere.


>
>
> -Matias
>
>
>
>
>
> think it should. This platform specific warning should appear there as a
> doxygen  @warning
> Perhaps we need to start a trend of adding a doxygen platform specific
> module called "PLATFORM SPECIFICS", then we can add information with the
> @addtogroup platform_specifics and users across platforms will know where
> to look for this sort of information.
>
>
>
> The best place for this sort of implementation documentation is in the
> comments in the C code itself. We just want a reminder to future
> maintainers of the code of a shortcut that was taken for performance
> reasons and the cautions that need to be observed as a result.
>
>
>
> I dont agree, too many implementations copy this code, they need to be
> aware that a normal assumption is broken when they build upon it in their
> implementation.
>
>
>
> Blindly copying code is never a good idea. However, if you copy it its
> function is unchanged, so that has no effect. The only way you get in
> trouble is by copying and then changing other things without understanding
> what you're doing. That's always a recipe for trouble.
>
>
>
>
>
>
>
> If we want to have these sort of notes be collated as part of a
> "Maintainer's Guide" for odp-linux, that would seem a worthwhile project.
> Something to consider adding for Tiger Moth?
>
>
>
> I think it has to be in the implementer's guide since implementers often
> use odp-linux as the starting point, we need to warn them. It also has to
> be in the API guide if these structs will be seen by an application.
>
>
>
> I think it needs to happen before Monarch since this behaviour is
> unexpected and we need to make sure it is noticed as the other
> implementations home in on a fully compliant Monarch API
>
>
>
>
>
> Again, the fields that this patch deletes were never exposed as part of
> any ODP API. They were positioning for future extensions which never
> materialized. If they do (via new APIs) then they will be added back as
> needed. There's nothing nefarious going on here. The only change is that
> before you could add a new field and be somewhat sloppy about it. Now you
> have to think about what you're doing.
>
>
>
>
>
>
>
>
>
>
>  typedef struct {
> >         /* common buffer header */
> >         odp_buffer_hdr_t buf_hdr;
> >
> > +       /* Following members are initialized by packet_init() */
> >         input_flags_t  input_flags;
> >         error_flags_t  error_flags;
> >         output_flags_t output_flags;
> > @@ -142,15 +146,16 @@ typedef struct {
> >         uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */
> >         uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also
> > ICMP) */
> >
> > -       uint32_t l3_len;         /**< Layer 3 length */
> > -       uint32_t l4_len;         /**< Layer 4 length */
> > -
> >         uint32_t frame_len;
> >         uint32_t headroom;
> >         uint32_t tailroom;
> >
> >         odp_pktio_t input;
> >
> > +       /* Members below are not initialized by packet_init() */
> > +       uint32_t l3_len;         /**< Layer 3 length */
> > +       uint32_t l4_len;         /**< Layer 4 length */
> > +
> >         uint32_t flow_hash;      /**< Flow hash value */
> >         odp_time_t timestamp;    /**< Timestamp value */
> >
> > diff --git a/platform/linux-generic/odp_packet.c
> > b/platform/linux-generic/odp_packet.c
> > index 4f523c9..8dde404 100644
> > --- a/platform/linux-generic/odp_packet.c
> > +++ b/platform/linux-generic/odp_packet.c
> > @@ -49,19 +49,11 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
> >  static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
> >                         size_t size, int parse)
> >  {
> > -       /*
> > -       * Reset parser metadata.  Note that we clear via memset to make
> > -       * this routine indepenent of any additional adds to packet
> > metadata.
> > -       */
> > -       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
> > buf_hdr);
> > -       uint8_t *start;
> > -       size_t len;
> > +       pkt_hdr->input_flags.all  = 0;
> > +       pkt_hdr->output_flags.all = 0;
> > +       pkt_hdr->error_flags.all  = 0;
> >
> > -       start = (uint8_t *)pkt_hdr + start_offset;
> > -       len = sizeof(odp_packet_hdr_t) - start_offset;
> > -       memset(start, 0, len);
> > -
> > -       /* Set metadata items that initialize to non-zero values */
> > +       pkt_hdr->l2_offset = 0;
> >         pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
> >         pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
> >
> > @@ -79,6 +71,8 @@ static void packet_init(pool_entry_t *pool,
> > odp_packet_hdr_t *pkt_hdr,
> >         pkt_hdr->tailroom  =
> >                 (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
> >                 (pool->s.headroom + size);
> > +
> > +       pkt_hdr->input = ODP_PKTIO_INVALID;
> >  }
> >
> >  odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse)
> > --
> > 1.9.1
> >
> > _______________________________________________
> > lng-odp mailing list
> > lng-odp@lists.linaro.org
> > https://lists.linaro.org/mailman/listinfo/lng-odp
> >
>
>
> --
> Mike Holmes
> Technical Manager - Linaro Networking Group
>
> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
> "Work should be fun and collaborative, the rest follows"
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
>
>
>
>
>
>
> --
>
> Mike Holmes
>
> Technical Manager - Linaro Networking Group
>
> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
>
> "Work should be fun and collaborative, the rest follows"
>
>
>
>
>
Bill Fischofer May 18, 2016, 9 p.m. UTC | #6
On Wed, May 18, 2016 at 12:31 PM, Mike Holmes <mike.holmes@linaro.org>
wrote:

>
>
> On 18 May 2016 at 02:17, Elo, Matias (Nokia - FI/Espoo) <
> matias.elo@nokia.com> wrote:
>
>>
>>
>>
>>
>> *From:* Bill Fischofer [mailto:bill.fischofer@linaro.org]
>> *Sent:* Tuesday, May 17, 2016 9:46 PM
>> *To:* Mike Holmes <mike.holmes@linaro.org>
>> *Cc:* Elo, Matias (Nokia - FI/Espoo) <matias.elo@nokia.com>; lng-odp <
>> lng-odp@lists.linaro.org>
>> *Subject:* Re: [lng-odp] [PATCH v2 5/5] linux-generic: packet:
>> initialize only selected odp_packet_hdr_t members
>>
>>
>>
>>
>>
>>
>>
>> On Tue, May 17, 2016 at 12:42 PM, Mike Holmes <mike.holmes@linaro.org>
>> wrote:
>>
>>
>>
>>
>>
>> On 16 May 2016 at 18:52, Bill Fischofer <bill.fischofer@linaro.org>
>> wrote:
>>
>>
>>
>>
>>
>> On Mon, May 16, 2016 at 9:25 AM, Mike Holmes <mike.holmes@linaro.org>
>> wrote:
>>
>> On 16 May 2016 at 05:50, Matias Elo <matias.elo@nokia.com> wrote:
>>
>> > Using memset to initialize struct odp_packet_hdr_t contents
>> > to 0 has a significant overhead. Instead, initialize only
>> > the required members of the struct.
>> >
>> > Signed-off-by: Matias Elo <matias.elo@nokia.com>
>> > ---
>> >  platform/linux-generic/include/odp_packet_internal.h | 13 +++++++++----
>> >  platform/linux-generic/odp_packet.c                  | 18
>> > ++++++------------
>> >  2 files changed, 15 insertions(+), 16 deletions(-)
>> >
>> > diff --git a/platform/linux-generic/include/odp_packet_internal.h
>> > b/platform/linux-generic/include/odp_packet_internal.h
>> > index 1306b05..c87bc9f 100644
>> > --- a/platform/linux-generic/include/odp_packet_internal.h
>> > +++ b/platform/linux-generic/include/odp_packet_internal.h
>> > @@ -4,7 +4,6 @@
>> >   * SPDX-License-Identifier:     BSD-3-Clause
>> >   */
>> >
>> -
>> >  /**
>> >   * @file
>> >   *
>> > @@ -129,11 +128,16 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) ==
>> > sizeof(uint32_t),
>> >
>> >  /**
>> >   * Internal Packet header
>> > + *
>> > + * To optimize fast path performance this struct is not initialized to
>> > zero in
>> > + * packet_init(). Because of this any new fields added must be reviewed
>> > for
>> > + * initialization requirements.
>> >   */
>>
>> This file will not contribute to the generated API documentation and I
>>
>>
>>
>> It's not relevant to the API, only to the odp-linux implementation of the
>> API.
>>
>>
>>
>> Exactly, as a user of the odp-linux implementation dont I want to know
>> that some fields are not set ?
>>
>>
>>
>> No, because the internals of odp-linux (or any other implementation) are
>> not visible to users. The only thing users see is what the API exposes.
>> These optimizations have no impact on the API. The only people who care
>> about this are the maintainers of odp-linux.
>>
>>
>>
>> This is exactly what was done here. Either the uninitialized members are
>> not visible to the user at all (op_result, l3_len, l4_len) or the input
>> flags are used the check if the values are valid (flow_hash, timetamp).
>>
>>
> I am clearly missing something, I will leave it that I dont think we make
> it clear enough to any reusers and our own implementers becasue that /**
> doxygen comment is not published anywhere.
>

If someone is reusing code they should be looking at that code (and the C
comments within it) before doing so blindly. That's why I wanted to see the
C comments added as a note to the reader of the code. I don't think you
expect someone to look elsewhere for that sort of information. Besides, we
currently have no place to put such doxygen output as this would logically
be part of the internal documentation for a specific implementation of ODP
rather than part of either the general or platform-specific documentation
of the ODP API spec.

Basically what these changes do is remove otherwise unused internal
variables. That's all. They were put there originally in anticipation that
they might be externalized via ODP APIs, but that hasn't happened. If it
does happen in the future then this code (as part of the implementation of
those new APIs) would be modified. For now, given that Matias has
demonstrated a meaningful performance advantage to deleting them, that
seems a very reasonable thing to do.


>
>>
>>
>> -Matias
>>
>>
>>
>>
>>
>> think it should. This platform specific warning should appear there as a
>> doxygen  @warning
>> Perhaps we need to start a trend of adding a doxygen platform specific
>> module called "PLATFORM SPECIFICS", then we can add information with the
>> @addtogroup platform_specifics and users across platforms will know where
>> to look for this sort of information.
>>
>>
>>
>> The best place for this sort of implementation documentation is in the
>> comments in the C code itself. We just want a reminder to future
>> maintainers of the code of a shortcut that was taken for performance
>> reasons and the cautions that need to be observed as a result.
>>
>>
>>
>> I dont agree, too many implementations copy this code, they need to be
>> aware that a normal assumption is broken when they build upon it in their
>> implementation.
>>
>>
>>
>> Blindly copying code is never a good idea. However, if you copy it its
>> function is unchanged, so that has no effect. The only way you get in
>> trouble is by copying and then changing other things without understanding
>> what you're doing. That's always a recipe for trouble.
>>
>>
>>
>>
>>
>>
>>
>> If we want to have these sort of notes be collated as part of a
>> "Maintainer's Guide" for odp-linux, that would seem a worthwhile project.
>> Something to consider adding for Tiger Moth?
>>
>>
>>
>> I think it has to be in the implementer's guide since implementers often
>> use odp-linux as the starting point, we need to warn them. It also has to
>> be in the API guide if these structs will be seen by an application.
>>
>>
>>
>> I think it needs to happen before Monarch since this behaviour is
>> unexpected and we need to make sure it is noticed as the other
>> implementations home in on a fully compliant Monarch API
>>
>>
>>
>>
>>
>> Again, the fields that this patch deletes were never exposed as part of
>> any ODP API. They were positioning for future extensions which never
>> materialized. If they do (via new APIs) then they will be added back as
>> needed. There's nothing nefarious going on here. The only change is that
>> before you could add a new field and be somewhat sloppy about it. Now you
>> have to think about what you're doing.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>  typedef struct {
>> >         /* common buffer header */
>> >         odp_buffer_hdr_t buf_hdr;
>> >
>> > +       /* Following members are initialized by packet_init() */
>> >         input_flags_t  input_flags;
>> >         error_flags_t  error_flags;
>> >         output_flags_t output_flags;
>> > @@ -142,15 +146,16 @@ typedef struct {
>> >         uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */
>> >         uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also
>> > ICMP) */
>> >
>> > -       uint32_t l3_len;         /**< Layer 3 length */
>> > -       uint32_t l4_len;         /**< Layer 4 length */
>> > -
>> >         uint32_t frame_len;
>> >         uint32_t headroom;
>> >         uint32_t tailroom;
>> >
>> >         odp_pktio_t input;
>> >
>> > +       /* Members below are not initialized by packet_init() */
>> > +       uint32_t l3_len;         /**< Layer 3 length */
>> > +       uint32_t l4_len;         /**< Layer 4 length */
>> > +
>> >         uint32_t flow_hash;      /**< Flow hash value */
>> >         odp_time_t timestamp;    /**< Timestamp value */
>> >
>> > diff --git a/platform/linux-generic/odp_packet.c
>> > b/platform/linux-generic/odp_packet.c
>> > index 4f523c9..8dde404 100644
>> > --- a/platform/linux-generic/odp_packet.c
>> > +++ b/platform/linux-generic/odp_packet.c
>> > @@ -49,19 +49,11 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
>> >  static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
>> >                         size_t size, int parse)
>> >  {
>> > -       /*
>> > -       * Reset parser metadata.  Note that we clear via memset to make
>> > -       * this routine indepenent of any additional adds to packet
>> > metadata.
>> > -       */
>> > -       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>> > buf_hdr);
>> > -       uint8_t *start;
>> > -       size_t len;
>> > +       pkt_hdr->input_flags.all  = 0;
>> > +       pkt_hdr->output_flags.all = 0;
>> > +       pkt_hdr->error_flags.all  = 0;
>> >
>> > -       start = (uint8_t *)pkt_hdr + start_offset;
>> > -       len = sizeof(odp_packet_hdr_t) - start_offset;
>> > -       memset(start, 0, len);
>> > -
>> > -       /* Set metadata items that initialize to non-zero values */
>> > +       pkt_hdr->l2_offset = 0;
>> >         pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
>> >         pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
>> >
>> > @@ -79,6 +71,8 @@ static void packet_init(pool_entry_t *pool,
>> > odp_packet_hdr_t *pkt_hdr,
>> >         pkt_hdr->tailroom  =
>> >                 (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
>> >                 (pool->s.headroom + size);
>> > +
>> > +       pkt_hdr->input = ODP_PKTIO_INVALID;
>> >  }
>> >
>> >  odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse)
>> > --
>> > 1.9.1
>> >
>> > _______________________________________________
>> > lng-odp mailing list
>> > lng-odp@lists.linaro.org
>> > https://lists.linaro.org/mailman/listinfo/lng-odp
>> >
>>
>>
>> --
>> Mike Holmes
>> Technical Manager - Linaro Networking Group
>>
>> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
>> "Work should be fun and collaborative, the rest follows"
>>
>> _______________________________________________
>> lng-odp mailing list
>> lng-odp@lists.linaro.org
>> https://lists.linaro.org/mailman/listinfo/lng-odp
>>
>>
>>
>>
>>
>>
>>
>> --
>>
>> Mike Holmes
>>
>> Technical Manager - Linaro Networking Group
>>
>> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
>>
>> "Work should be fun and collaborative, the rest follows"
>>
>>
>>
>>
>>
>
>
>
> --
> Mike Holmes
> Technical Manager - Linaro Networking Group
> Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
> "Work should be fun and collaborative, the rest follows"
>
>
>
diff mbox

Patch

diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
index 1306b05..c87bc9f 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -4,7 +4,6 @@ 
  * SPDX-License-Identifier:     BSD-3-Clause
  */
 
-
 /**
  * @file
  *
@@ -129,11 +128,16 @@  ODP_STATIC_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t),
 
 /**
  * Internal Packet header
+ *
+ * To optimize fast path performance this struct is not initialized to zero in
+ * packet_init(). Because of this any new fields added must be reviewed for
+ * initialization requirements.
  */
 typedef struct {
 	/* common buffer header */
 	odp_buffer_hdr_t buf_hdr;
 
+	/* Following members are initialized by packet_init() */
 	input_flags_t  input_flags;
 	error_flags_t  error_flags;
 	output_flags_t output_flags;
@@ -142,15 +146,16 @@  typedef struct {
 	uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */
 	uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also ICMP) */
 
-	uint32_t l3_len;         /**< Layer 3 length */
-	uint32_t l4_len;         /**< Layer 4 length */
-
 	uint32_t frame_len;
 	uint32_t headroom;
 	uint32_t tailroom;
 
 	odp_pktio_t input;
 
+	/* Members below are not initialized by packet_init() */
+	uint32_t l3_len;         /**< Layer 3 length */
+	uint32_t l4_len;         /**< Layer 4 length */
+
 	uint32_t flow_hash;      /**< Flow hash value */
 	odp_time_t timestamp;    /**< Timestamp value */
 
diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c
index 4f523c9..8dde404 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -49,19 +49,11 @@  void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
 static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
 			size_t size, int parse)
 {
-       /*
-	* Reset parser metadata.  Note that we clear via memset to make
-	* this routine indepenent of any additional adds to packet metadata.
-	*/
-	const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr);
-	uint8_t *start;
-	size_t len;
+	pkt_hdr->input_flags.all  = 0;
+	pkt_hdr->output_flags.all = 0;
+	pkt_hdr->error_flags.all  = 0;
 
-	start = (uint8_t *)pkt_hdr + start_offset;
-	len = sizeof(odp_packet_hdr_t) - start_offset;
-	memset(start, 0, len);
-
-	/* Set metadata items that initialize to non-zero values */
+	pkt_hdr->l2_offset = 0;
 	pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
 	pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
 
@@ -79,6 +71,8 @@  static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
 	pkt_hdr->tailroom  =
 		(pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
 		(pool->s.headroom + size);
+
+	pkt_hdr->input = ODP_PKTIO_INVALID;
 }
 
 odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse)