diff mbox

[3/7] ODP Packet Flags API

Message ID 1392639281-2753-4-git-send-email-carl.wallen@linaro.org
State Accepted, archived
Commit 364208558d33cb54a09fa7ba6c493f2db8882d41
Headers show

Commit Message

Carl Wallen Feb. 17, 2014, 12:14 p.m. UTC
Add ODP Packet Flags API funcs to access the error, input and output
flags set by packet IO.

Signed-off-by: Carl Wallen <carl.wallen@linaro.org>
---
 include/odp.h                                      |   1 +
 include/odp_packet_flags.h                         | 189 +++++++++++++++++++++
 platform/linux-generic/Makefile                    |   1 +
 .../linux-generic/include/odp_packet_internal.h    |  95 ++++++++---
 platform/linux-generic/source/odp_packet.c         |  18 +-
 platform/linux-generic/source/odp_packet_flags.c   | 116 +++++++++++++
 6 files changed, 383 insertions(+), 37 deletions(-)
 create mode 100644 include/odp_packet_flags.h
 create mode 100644 platform/linux-generic/source/odp_packet_flags.c

Comments

Ola Liljedahl Feb. 17, 2014, 1:18 p.m. UTC | #1
odp_packet_flags.[ch]:
Again too many functions which I don't think are necessary for ODP itself.
So what's the reason for all of these functions? Do you think these are
checks that might be HW-accelerated and thus deserve inclusion into ODP?

Regarding the implementation, is it the best choice to use a set of
discrete bits? It is not a scalable approach as the number of supported
protocols increase.



On 17 February 2014 13:14, Carl Wallen <carl.wallen@linaro.org> wrote:

> Add ODP Packet Flags API funcs to access the error, input and output
> flags set by packet IO.
>
> Signed-off-by: Carl Wallen <carl.wallen@linaro.org>
> ---
>  include/odp.h                                      |   1 +
>  include/odp_packet_flags.h                         | 189
> +++++++++++++++++++++
>  platform/linux-generic/Makefile                    |   1 +
>  .../linux-generic/include/odp_packet_internal.h    |  95 ++++++++---
>  platform/linux-generic/source/odp_packet.c         |  18 +-
>  platform/linux-generic/source/odp_packet_flags.c   | 116 +++++++++++++
>  6 files changed, 383 insertions(+), 37 deletions(-)
>  create mode 100644 include/odp_packet_flags.h
>  create mode 100644 platform/linux-generic/source/odp_packet_flags.c
>
> diff --git a/include/odp.h b/include/odp.h
> index 08c7c31..6a52346 100644
> --- a/include/odp.h
> +++ b/include/odp.h
> @@ -295,6 +295,7 @@ extern "C" {
>  #include <odp_schedule.h>
>  #include <odp_sync.h>
>  #include <odp_packet.h>
> +#include <odp_packet_flags.h>
>  #include <odp_packet_io.h>
>
>  #ifdef __cplusplus
> diff --git a/include/odp_packet_flags.h b/include/odp_packet_flags.h
> new file mode 100644
> index 0000000..eb9315b
> --- /dev/null
> +++ b/include/odp_packet_flags.h
> @@ -0,0 +1,189 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +
> +/**
> + * @file
> + *
> + * ODP packet flags
> + */
> +
> +#ifndef ODP_PACKET_FLAGS_H_
> +#define ODP_PACKET_FLAGS_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <odp_std_types.h>
> +#include <odp_packet.h>
> +
> +/**
> + * Check for packet errors
> + *
> + * Checks all error flags at once.
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet has errors, 0 otherwise
> + */
> +int odp_packet_error(odp_packet_t pkt);
> +
> +/**
> + * Check if error was 'frame length' error
> + *
> + * @param pkt Packet handle
> + * @return 1 if frame length error detected, 0 otherwise
> + */
> +int odp_packet_errflag_frame_len(odp_packet_t pkt);
> +
> +/**
> + * Check for L2 header, e.g. ethernet
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains a valid & known L2 header, 0 otherwise
> + */
> +int odp_packet_inflag_l2(odp_packet_t pkt);
> +
> +/**
> + * Check for L3 header, e.g. IPv4, IPv6
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains a valid & known L3 header, 0 otherwise
> + */
> +int odp_packet_inflag_l3(odp_packet_t pkt);
> +
> +/**
> + * Check for L4 header, e.g. UDP, TCP, SCTP (also ICMP)
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains a valid & known L4 header, 0 otherwise
> + */
> +int odp_packet_inflag_l4(odp_packet_t pkt);
> +
> +/**
> + * Check for Ethernet header
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains a valid eth header, 0 otherwise
> + */
> +int odp_packet_inflag_eth(odp_packet_t pkt);
> +
> +/**
> + * Check for jumbo frame
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains jumbo frame, 0 otherwise
> + */
> +int odp_packet_inflag_jumbo(odp_packet_t pkt);
> +
> +/**
> + * Check for VLAN
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains a VLAN header, 0 otherwise
> + */
> +int odp_packet_inflag_vlan(odp_packet_t pkt);
> +
> +/**
> + * Check for VLAN QinQ (stacked VLAN)
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains a VLAN QinQ header, 0 otherwise
> + */
> +int odp_packet_inflag_vlan_qinq(odp_packet_t pkt);
> +
> +/**
> + * Check for ARP
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains an ARP header, 0 otherwise
> + */
> +int odp_packet_inflag_arp(odp_packet_t pkt);
> +
> +/**
> + * Check for IPv4
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains an IPv4 header, 0 otherwise
> + */
> +int odp_packet_inflag_ipv4(odp_packet_t pkt);
> +
> +/**
> + * Check for IPv6
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains an IPv6 header, 0 otherwise
> + */
> +int odp_packet_inflag_ipv6(odp_packet_t pkt);
> +
> +/**
> + * Check for IP fragment
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet is an IP fragment, 0 otherwise
> + */
> +int odp_packet_inflag_ipfrag(odp_packet_t pkt);
> +
> +/**
> + * Check for IP options
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains IP options, 0 otherwise
> + */
> +int odp_packet_inflag_ipopt(odp_packet_t pkt);
> +
> +/**
> + * Check for IPSec
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet requires IPSec processing, 0 otherwise
> + */
> +int odp_packet_inflag_ipsec(odp_packet_t pkt);
> +
> +/**
> + * Check for UDP
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains a UDP header, 0 otherwise
> + */
> +int odp_packet_inflag_udp(odp_packet_t pkt);
> +
> +/**
> + * Check for TCP
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains a TCP header, 0 otherwise
> + */
> +int odp_packet_inflag_tcp(odp_packet_t pkt);
> +
> +/**
> + * Check for SCTP
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains an SCTP header, 0 otherwise
> + */
> +int odp_packet_inflag_sctp(odp_packet_t pkt);
> +
> +/**
> + * Check for ICMP
> + *
> + * @param pkt Packet handle
> + * @return 1 if packet contains an ICMP header, 0 otherwise
> + */
> +int odp_packet_inflag_icmp(odp_packet_t pkt);
> +
> +/**
> + * Request L4 checksum calculation
> + *
> + * @param pkt Packet handle
> + */
> +void odp_packet_outflag_l4_chksum(odp_packet_t pkt);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/platform/linux-generic/Makefile
> b/platform/linux-generic/Makefile
> index f665683..b640928 100644
> --- a/platform/linux-generic/Makefile
> +++ b/platform/linux-generic/Makefile
> @@ -54,6 +54,7 @@ OBJS    += $(OBJ_DIR)/odp_coremask.o
>  OBJS    += $(OBJ_DIR)/odp_init.o
>  OBJS    += $(OBJ_DIR)/odp_linux.o
>  OBJS    += $(OBJ_DIR)/odp_packet.o
> +OBJS    += $(OBJ_DIR)/odp_packet_flags.o
>  OBJS    += $(OBJ_DIR)/odp_packet_io.o
>  OBJS    += $(OBJ_DIR)/odp_packet_socket.o
>  OBJS    += $(OBJ_DIR)/odp_queue.o
> diff --git a/platform/linux-generic/include/odp_packet_internal.h
> b/platform/linux-generic/include/odp_packet_internal.h
> index afef976..f0dda95 100644
> --- a/platform/linux-generic/include/odp_packet_internal.h
> +++ b/platform/linux-generic/include/odp_packet_internal.h
> @@ -25,59 +25,98 @@ extern "C" {
>  #include <odp_packet.h>
>  #include <odp_packet_io.h>
>
> -typedef struct {
> -       uint32_t l2:1;
> -       uint32_t l3:1;
> -       uint32_t l4:1;
> -
> -       uint32_t macsec:1;
> -       uint32_t vlan:1;
> -       uint32_t vlan_double:1;
> -       uint32_t ipv4:1;
> -       uint32_t ipv6:1;
> -       uint32_t ip_frag:1;
> -       uint32_t udp:1;
> -       uint32_t tcp:1;
> -       uint32_t icmp:1;
> -} proto_flags_t;
> +/**
> + * Packet input & protocol flags
> + */
> +typedef union {
> +       /* All input flags */
> +       uint32_t all;
>
> -typedef struct {
> -       uint32_t frame_len:1;
> -       uint32_t l2_chksum:1;
> -       uint32_t ip_err:1;
> -       uint32_t tcp_err:1;
> -       uint32_t udp_err:1;
> +       /* Bitfield flags for each protocol */
> +       uint32_t l2:1;        /**< known L2 protocol present */
> +       uint32_t l3:1;        /**< known L3 protocol present */
> +       uint32_t l4:1;        /**< known L4 protocol present */
> +
> +       uint32_t eth:1;       /**< Ethernet */
> +       uint32_t jumbo:1;     /**< Jumbo frame */
> +       uint32_t vlan:1;      /**< VLAN hdr found */
> +       uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */
> +
> +       uint32_t arp:1;       /**< ARP */
> +
> +       uint32_t ipv4:1;      /**< IPv4 */
> +       uint32_t ipv6:1;      /**< IPv6 */
> +       uint32_t ipfrag:1;    /**< IP fragment */
> +       uint32_t ipopt:1;     /**< IP optional headers */
> +       uint32_t ipsec;       /**< IPSec decryption may be needed */
> +
> +       uint32_t udp:1;       /**< UDP */
> +       uint32_t tcp:1;       /**< TCP */
> +       uint32_t sctp:1;      /**< SCTP */
> +       uint32_t icmp:1;      /**< ICMP */
> +} input_flags_t;
> +
> +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t),
> INPUT_FLAGS_SIZE_ERROR);
> +
> +/**
> + * Packet error flags
> + */
> +typedef union {
> +       /* All error flags */
> +       uint32_t all;
> +
> +       /* Bitfield flags for each detected error */
> +       uint32_t frame_len:1; /**< Frame length error */
> +       uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD */
> +       uint32_t ip_err:1;    /**< IP error,  checks TBD */
> +       uint32_t tcp_err:1;   /**< TCP error, checks TBD */
> +       uint32_t udp_err:1;   /**< UDP error, checks TBD */
>  } error_flags_t;
>
> -typedef struct {
> -       uint32_t calc_l4_chksum:1;
> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t),
> ERROR_FLAGS_SIZE_ERROR);
> +
> +/**
> + * Packet output flags
> + */
> +typedef union {
> +       /* All output flags */
> +       uint32_t all;
> +
> +       /* Bitfield flags for each output option */
> +       uint32_t l4_chksum:1; /**< Request L4 checksum calculation */
>  } output_flags_t;
>
> +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t),
> OUTPUT_FLAGS_SIZE_ERROR);
> +
>  /**
>   * Internal Packet header
>   */
> -typedef struct odp_packet_hdr_t {
> +typedef struct {
>         /* common buffer header */
>         odp_buffer_hdr_t buf_hdr;
>
> -       proto_flags_t  proto_flags;
> +       input_flags_t  input_flags;
>         error_flags_t  error_flags;
>         output_flags_t output_flags;
>
> -       uint32_t l2_offset;
> -       uint32_t l3_offset;
> -       uint32_t l4_offset;
> +       uint32_t frame_offset; /**< offset to start of frame, even on
> error */
> +       uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */
> +       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 frame_len;
>
>         odp_pktio_t input;
>
> +       uint32_t pad;
>         uint8_t payload[];
>
>  } odp_packet_hdr_t;
>
>  ODP_ASSERT(sizeof(odp_packet_hdr_t) == ODP_OFFSETOF(odp_packet_hdr_t,
> payload),
>            ODP_PACKET_HDR_T__SIZE_ERR);
> +ODP_ASSERT(sizeof(odp_packet_hdr_t) % sizeof(uint64_t) == 0,
> +          ODP_PACKET_HDR_T__SIZE_ERR2);
>
>  /**
>   * Return the packet header
> diff --git a/platform/linux-generic/source/odp_packet.c
> b/platform/linux-generic/source/odp_packet.c
> index 6b06f76..6ee2c5b 100644
> --- a/platform/linux-generic/source/odp_packet.c
> +++ b/platform/linux-generic/source/odp_packet.c
> @@ -124,7 +124,7 @@ void odp_packet_parse(odp_packet_t pkt, size_t len,
> size_t l2_offset)
>         if (odp_unlikely(len < ODP_ETH_LEN_MIN))
>                 pkt_hdr->error_flags.frame_len = 1;
>
> -       pkt_hdr->proto_flags.l2 = 1;
> +       pkt_hdr->input_flags.l2 = 1;
>         pkt_hdr->l2_offset = l2_offset;
>         eth = (odp_ethhdr_t *)odp_packet_l2(pkt);
>
> @@ -132,25 +132,25 @@ void odp_packet_parse(odp_packet_t pkt, size_t len,
> size_t l2_offset)
>         vlan = (odp_vlanhdr_t *)&eth->type;
>
>         if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
> -               pkt_hdr->proto_flags.vlan_double = 1;
> +               pkt_hdr->input_flags.vlan_qinq = 1;
>                 ethtype = odp_be_to_cpu_16(vlan->tpid);
>                 offset += sizeof(odp_vlanhdr_t);
>                 vlan = &vlan[1];
>         }
>
>         if (ethtype == ODP_ETHTYPE_VLAN) {
> -               pkt_hdr->proto_flags.vlan = 1;
> +               pkt_hdr->input_flags.vlan = 1;
>                 ethtype = odp_be_to_cpu_16(vlan->tpid);
>                 offset += sizeof(odp_vlanhdr_t);
>         }
>
> -       pkt_hdr->proto_flags.l3 = 1;
> +       pkt_hdr->input_flags.l3 = 1;
>         pkt_hdr->l3_offset = l2_offset + ODP_ETHHDR_LEN + offset;
>
>         if (ethtype == ODP_ETHTYPE_IPV4) {
>                 uint8_t ihl;
>
> -               pkt_hdr->proto_flags.ipv4 = 1;
> +               pkt_hdr->input_flags.ipv4 = 1;
>                 ip = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
>
>                 ihl = ODP_IPV4HDR_IHL(ip->ver_ihl);
> @@ -159,19 +159,19 @@ void odp_packet_parse(odp_packet_t pkt, size_t len,
> size_t l2_offset)
>                         return;
>                 }
>
> -               pkt_hdr->proto_flags.l4 = 1;
> +               pkt_hdr->input_flags.l4 = 1;
>                 pkt_hdr->l4_offset = pkt_hdr->l3_offset +
>                                      sizeof(uint32_t) * ihl;
>
>                 switch (ip->proto) {
>                 case ODP_IPPROTO_UDP:
> -                       pkt_hdr->proto_flags.udp = 1;
> +                       pkt_hdr->input_flags.udp = 1;
>                         break;
>                 case ODP_IPPROTO_TCP:
> -                       pkt_hdr->proto_flags.tcp = 1;
> +                       pkt_hdr->input_flags.tcp = 1;
>                         break;
>                 case ODP_IPPROTO_ICMP:
> -                       pkt_hdr->proto_flags.icmp = 1;
> +                       pkt_hdr->input_flags.icmp = 1;
>                         break;
>                 }
>         }
> diff --git a/platform/linux-generic/source/odp_packet_flags.c
> b/platform/linux-generic/source/odp_packet_flags.c
> new file mode 100644
> index 0000000..0fd0aa9
> --- /dev/null
> +++ b/platform/linux-generic/source/odp_packet_flags.c
> @@ -0,0 +1,116 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> + #include <odp_packet_flags.h>
> + #include <odp_packet_internal.h>
> +
> +
> +int odp_packet_error(odp_packet_t pkt)
> +{
> +       return (odp_packet_hdr(pkt)->error_flags.all != 0);
> +}
> +
> +/* Get Error Flags */
> +
> +int odp_packet_errflag_frame_len(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->error_flags.frame_len;
> +}
> +
> +/* Get Input Flags */
> +
> +int odp_packet_inflag_l2(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.l2;
> +}
> +
> +int odp_packet_inflag_l3(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.l3;
> +}
> +
> +int odp_packet_inflag_l4(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.l4;
> +}
> +
> +int odp_packet_inflag_eth(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.eth;
> +}
> +
> +int odp_packet_inflag_jumbo(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.jumbo;
> +}
> +
> +int odp_packet_inflag_vlan(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.vlan;
> +}
> +
> +int odp_packet_inflag_vlan_qinq(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.vlan_qinq;
> +}
> +
> +int odp_packet_inflag_arp(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.arp;
> +}
> +
> +int odp_packet_inflag_ipv4(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.ipv4;
> +}
> +
> +int odp_packet_inflag_ipv6(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.ipv6;
> +}
> +
> +int odp_packet_inflag_ipfrag(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.ipfrag;
> +}
> +
> +int odp_packet_inflag_ipopt(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.ipopt;
> +}
> +
> +int odp_packet_inflag_ipsec(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.ipsec;
> +}
> +
> +int odp_packet_inflag_udp(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.udp;
> +}
> +
> +int odp_packet_inflag_tcp(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.tcp;
> +}
> +
> +int odp_packet_inflag_sctp(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.sctp;
> +}
> +
> +int odp_packet_inflag_icmp(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input_flags.icmp;
> +}
> +
> +/* Set Output Flags */
> +
> +void odp_packet_outflag_l4_chksum(odp_packet_t pkt)
> +{
> +       odp_packet_hdr(pkt)->output_flags.l4_chksum = 1;
> +}
> +
> --
> 1.8.5.3
>
> --
> You received this message because you are subscribed to the Google Groups
> "LNG ODP Sub-team - lng-odp@linaro.org" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to lng-odp+unsubscribe@linaro.org.
> To post to this group, send email to lng-odp@linaro.org.
> Visit this group at http://groups.google.com/a/linaro.org/group/lng-odp/.
> To view this discussion on the web visit
> https://groups.google.com/a/linaro.org/d/msgid/lng-odp/1392639281-2753-4-git-send-email-carl.wallen%40linaro.org
> .
> For more options, visit
> https://groups.google.com/a/linaro.org/groups/opt_out.
>
Mike Holmes Feb. 17, 2014, 5:06 p.m. UTC | #2
Do they make a useful addition to the internal API even if they don't have
a place in the public API ?

I could see some possibly utility when interacting with a regular user
space application, one that is communicating with ODP via a virtual
interface, maybe a control plane  interaction ?

Mike


On 17 February 2014 08:18, Ola Liljedahl <ola.liljedahl@linaro.org> wrote:

> odp_packet_flags.[ch]:
> Again too many functions which I don't think are necessary for ODP itself.
> So what's the reason for all of these functions? Do you think these are
> checks that might be HW-accelerated and thus deserve inclusion into ODP?
>
> Regarding the implementation, is it the best choice to use a set of
> discrete bits? It is not a scalable approach as the number of supported
> protocols increase.
>
>
>
> On 17 February 2014 13:14, Carl Wallen <carl.wallen@linaro.org> wrote:
>
>> Add ODP Packet Flags API funcs to access the error, input and output
>> flags set by packet IO.
>>
>> Signed-off-by: Carl Wallen <carl.wallen@linaro.org>
>> ---
>>  include/odp.h                                      |   1 +
>>  include/odp_packet_flags.h                         | 189
>> +++++++++++++++++++++
>>  platform/linux-generic/Makefile                    |   1 +
>>  .../linux-generic/include/odp_packet_internal.h    |  95 ++++++++---
>>  platform/linux-generic/source/odp_packet.c         |  18 +-
>>  platform/linux-generic/source/odp_packet_flags.c   | 116 +++++++++++++
>>  6 files changed, 383 insertions(+), 37 deletions(-)
>>  create mode 100644 include/odp_packet_flags.h
>>  create mode 100644 platform/linux-generic/source/odp_packet_flags.c
>>
>> diff --git a/include/odp.h b/include/odp.h
>> index 08c7c31..6a52346 100644
>> --- a/include/odp.h
>> +++ b/include/odp.h
>> @@ -295,6 +295,7 @@ extern "C" {
>>  #include <odp_schedule.h>
>>  #include <odp_sync.h>
>>  #include <odp_packet.h>
>> +#include <odp_packet_flags.h>
>>  #include <odp_packet_io.h>
>>
>>  #ifdef __cplusplus
>> diff --git a/include/odp_packet_flags.h b/include/odp_packet_flags.h
>> new file mode 100644
>> index 0000000..eb9315b
>> --- /dev/null
>> +++ b/include/odp_packet_flags.h
>> @@ -0,0 +1,189 @@
>> +/* Copyright (c) 2014, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +
>> +/**
>> + * @file
>> + *
>> + * ODP packet flags
>> + */
>> +
>> +#ifndef ODP_PACKET_FLAGS_H_
>> +#define ODP_PACKET_FLAGS_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#include <odp_std_types.h>
>> +#include <odp_packet.h>
>> +
>> +/**
>> + * Check for packet errors
>> + *
>> + * Checks all error flags at once.
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet has errors, 0 otherwise
>> + */
>> +int odp_packet_error(odp_packet_t pkt);
>> +
>> +/**
>> + * Check if error was 'frame length' error
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if frame length error detected, 0 otherwise
>> + */
>> +int odp_packet_errflag_frame_len(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for L2 header, e.g. ethernet
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains a valid & known L2 header, 0 otherwise
>> + */
>> +int odp_packet_inflag_l2(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for L3 header, e.g. IPv4, IPv6
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains a valid & known L3 header, 0 otherwise
>> + */
>> +int odp_packet_inflag_l3(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for L4 header, e.g. UDP, TCP, SCTP (also ICMP)
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains a valid & known L4 header, 0 otherwise
>> + */
>> +int odp_packet_inflag_l4(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for Ethernet header
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains a valid eth header, 0 otherwise
>> + */
>> +int odp_packet_inflag_eth(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for jumbo frame
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains jumbo frame, 0 otherwise
>> + */
>> +int odp_packet_inflag_jumbo(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for VLAN
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains a VLAN header, 0 otherwise
>> + */
>> +int odp_packet_inflag_vlan(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for VLAN QinQ (stacked VLAN)
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains a VLAN QinQ header, 0 otherwise
>> + */
>> +int odp_packet_inflag_vlan_qinq(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for ARP
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains an ARP header, 0 otherwise
>> + */
>> +int odp_packet_inflag_arp(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for IPv4
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains an IPv4 header, 0 otherwise
>> + */
>> +int odp_packet_inflag_ipv4(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for IPv6
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains an IPv6 header, 0 otherwise
>> + */
>> +int odp_packet_inflag_ipv6(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for IP fragment
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet is an IP fragment, 0 otherwise
>> + */
>> +int odp_packet_inflag_ipfrag(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for IP options
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains IP options, 0 otherwise
>> + */
>> +int odp_packet_inflag_ipopt(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for IPSec
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet requires IPSec processing, 0 otherwise
>> + */
>> +int odp_packet_inflag_ipsec(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for UDP
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains a UDP header, 0 otherwise
>> + */
>> +int odp_packet_inflag_udp(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for TCP
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains a TCP header, 0 otherwise
>> + */
>> +int odp_packet_inflag_tcp(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for SCTP
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains an SCTP header, 0 otherwise
>> + */
>> +int odp_packet_inflag_sctp(odp_packet_t pkt);
>> +
>> +/**
>> + * Check for ICMP
>> + *
>> + * @param pkt Packet handle
>> + * @return 1 if packet contains an ICMP header, 0 otherwise
>> + */
>> +int odp_packet_inflag_icmp(odp_packet_t pkt);
>> +
>> +/**
>> + * Request L4 checksum calculation
>> + *
>> + * @param pkt Packet handle
>> + */
>> +void odp_packet_outflag_l4_chksum(odp_packet_t pkt);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-generic/Makefile
>> b/platform/linux-generic/Makefile
>> index f665683..b640928 100644
>> --- a/platform/linux-generic/Makefile
>> +++ b/platform/linux-generic/Makefile
>> @@ -54,6 +54,7 @@ OBJS    += $(OBJ_DIR)/odp_coremask.o
>>  OBJS    += $(OBJ_DIR)/odp_init.o
>>  OBJS    += $(OBJ_DIR)/odp_linux.o
>>  OBJS    += $(OBJ_DIR)/odp_packet.o
>> +OBJS    += $(OBJ_DIR)/odp_packet_flags.o
>>  OBJS    += $(OBJ_DIR)/odp_packet_io.o
>>  OBJS    += $(OBJ_DIR)/odp_packet_socket.o
>>  OBJS    += $(OBJ_DIR)/odp_queue.o
>> diff --git a/platform/linux-generic/include/odp_packet_internal.h
>> b/platform/linux-generic/include/odp_packet_internal.h
>> index afef976..f0dda95 100644
>> --- a/platform/linux-generic/include/odp_packet_internal.h
>> +++ b/platform/linux-generic/include/odp_packet_internal.h
>> @@ -25,59 +25,98 @@ extern "C" {
>>  #include <odp_packet.h>
>>  #include <odp_packet_io.h>
>>
>> -typedef struct {
>> -       uint32_t l2:1;
>> -       uint32_t l3:1;
>> -       uint32_t l4:1;
>> -
>> -       uint32_t macsec:1;
>> -       uint32_t vlan:1;
>> -       uint32_t vlan_double:1;
>> -       uint32_t ipv4:1;
>> -       uint32_t ipv6:1;
>> -       uint32_t ip_frag:1;
>> -       uint32_t udp:1;
>> -       uint32_t tcp:1;
>> -       uint32_t icmp:1;
>> -} proto_flags_t;
>> +/**
>> + * Packet input & protocol flags
>> + */
>> +typedef union {
>> +       /* All input flags */
>> +       uint32_t all;
>>
>> -typedef struct {
>> -       uint32_t frame_len:1;
>> -       uint32_t l2_chksum:1;
>> -       uint32_t ip_err:1;
>> -       uint32_t tcp_err:1;
>> -       uint32_t udp_err:1;
>> +       /* Bitfield flags for each protocol */
>> +       uint32_t l2:1;        /**< known L2 protocol present */
>> +       uint32_t l3:1;        /**< known L3 protocol present */
>> +       uint32_t l4:1;        /**< known L4 protocol present */
>> +
>> +       uint32_t eth:1;       /**< Ethernet */
>> +       uint32_t jumbo:1;     /**< Jumbo frame */
>> +       uint32_t vlan:1;      /**< VLAN hdr found */
>> +       uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */
>> +
>> +       uint32_t arp:1;       /**< ARP */
>> +
>> +       uint32_t ipv4:1;      /**< IPv4 */
>> +       uint32_t ipv6:1;      /**< IPv6 */
>> +       uint32_t ipfrag:1;    /**< IP fragment */
>> +       uint32_t ipopt:1;     /**< IP optional headers */
>> +       uint32_t ipsec;       /**< IPSec decryption may be needed */
>> +
>> +       uint32_t udp:1;       /**< UDP */
>> +       uint32_t tcp:1;       /**< TCP */
>> +       uint32_t sctp:1;      /**< SCTP */
>> +       uint32_t icmp:1;      /**< ICMP */
>> +} input_flags_t;
>> +
>> +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t),
>> INPUT_FLAGS_SIZE_ERROR);
>> +
>> +/**
>> + * Packet error flags
>> + */
>> +typedef union {
>> +       /* All error flags */
>> +       uint32_t all;
>> +
>> +       /* Bitfield flags for each detected error */
>> +       uint32_t frame_len:1; /**< Frame length error */
>> +       uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD */
>> +       uint32_t ip_err:1;    /**< IP error,  checks TBD */
>> +       uint32_t tcp_err:1;   /**< TCP error, checks TBD */
>> +       uint32_t udp_err:1;   /**< UDP error, checks TBD */
>>  } error_flags_t;
>>
>> -typedef struct {
>> -       uint32_t calc_l4_chksum:1;
>> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t),
>> ERROR_FLAGS_SIZE_ERROR);
>> +
>> +/**
>> + * Packet output flags
>> + */
>> +typedef union {
>> +       /* All output flags */
>> +       uint32_t all;
>> +
>> +       /* Bitfield flags for each output option */
>> +       uint32_t l4_chksum:1; /**< Request L4 checksum calculation */
>>  } output_flags_t;
>>
>> +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t),
>> OUTPUT_FLAGS_SIZE_ERROR);
>> +
>>  /**
>>   * Internal Packet header
>>   */
>> -typedef struct odp_packet_hdr_t {
>> +typedef struct {
>>         /* common buffer header */
>>         odp_buffer_hdr_t buf_hdr;
>>
>> -       proto_flags_t  proto_flags;
>> +       input_flags_t  input_flags;
>>         error_flags_t  error_flags;
>>         output_flags_t output_flags;
>>
>> -       uint32_t l2_offset;
>> -       uint32_t l3_offset;
>> -       uint32_t l4_offset;
>> +       uint32_t frame_offset; /**< offset to start of frame, even on
>> error */
>> +       uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */
>> +       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 frame_len;
>>
>>         odp_pktio_t input;
>>
>> +       uint32_t pad;
>>         uint8_t payload[];
>>
>>  } odp_packet_hdr_t;
>>
>>  ODP_ASSERT(sizeof(odp_packet_hdr_t) == ODP_OFFSETOF(odp_packet_hdr_t,
>> payload),
>>            ODP_PACKET_HDR_T__SIZE_ERR);
>> +ODP_ASSERT(sizeof(odp_packet_hdr_t) % sizeof(uint64_t) == 0,
>> +          ODP_PACKET_HDR_T__SIZE_ERR2);
>>
>>  /**
>>   * Return the packet header
>> diff --git a/platform/linux-generic/source/odp_packet.c
>> b/platform/linux-generic/source/odp_packet.c
>> index 6b06f76..6ee2c5b 100644
>> --- a/platform/linux-generic/source/odp_packet.c
>> +++ b/platform/linux-generic/source/odp_packet.c
>> @@ -124,7 +124,7 @@ void odp_packet_parse(odp_packet_t pkt, size_t len,
>> size_t l2_offset)
>>         if (odp_unlikely(len < ODP_ETH_LEN_MIN))
>>                 pkt_hdr->error_flags.frame_len = 1;
>>
>> -       pkt_hdr->proto_flags.l2 = 1;
>> +       pkt_hdr->input_flags.l2 = 1;
>>         pkt_hdr->l2_offset = l2_offset;
>>         eth = (odp_ethhdr_t *)odp_packet_l2(pkt);
>>
>> @@ -132,25 +132,25 @@ void odp_packet_parse(odp_packet_t pkt, size_t len,
>> size_t l2_offset)
>>         vlan = (odp_vlanhdr_t *)&eth->type;
>>
>>         if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
>> -               pkt_hdr->proto_flags.vlan_double = 1;
>> +               pkt_hdr->input_flags.vlan_qinq = 1;
>>                 ethtype = odp_be_to_cpu_16(vlan->tpid);
>>                 offset += sizeof(odp_vlanhdr_t);
>>                 vlan = &vlan[1];
>>         }
>>
>>         if (ethtype == ODP_ETHTYPE_VLAN) {
>> -               pkt_hdr->proto_flags.vlan = 1;
>> +               pkt_hdr->input_flags.vlan = 1;
>>                 ethtype = odp_be_to_cpu_16(vlan->tpid);
>>                 offset += sizeof(odp_vlanhdr_t);
>>         }
>>
>> -       pkt_hdr->proto_flags.l3 = 1;
>> +       pkt_hdr->input_flags.l3 = 1;
>>         pkt_hdr->l3_offset = l2_offset + ODP_ETHHDR_LEN + offset;
>>
>>         if (ethtype == ODP_ETHTYPE_IPV4) {
>>                 uint8_t ihl;
>>
>> -               pkt_hdr->proto_flags.ipv4 = 1;
>> +               pkt_hdr->input_flags.ipv4 = 1;
>>                 ip = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
>>
>>                 ihl = ODP_IPV4HDR_IHL(ip->ver_ihl);
>> @@ -159,19 +159,19 @@ void odp_packet_parse(odp_packet_t pkt, size_t len,
>> size_t l2_offset)
>>                         return;
>>                 }
>>
>> -               pkt_hdr->proto_flags.l4 = 1;
>> +               pkt_hdr->input_flags.l4 = 1;
>>                 pkt_hdr->l4_offset = pkt_hdr->l3_offset +
>>                                      sizeof(uint32_t) * ihl;
>>
>>                 switch (ip->proto) {
>>                 case ODP_IPPROTO_UDP:
>> -                       pkt_hdr->proto_flags.udp = 1;
>> +                       pkt_hdr->input_flags.udp = 1;
>>                         break;
>>                 case ODP_IPPROTO_TCP:
>> -                       pkt_hdr->proto_flags.tcp = 1;
>> +                       pkt_hdr->input_flags.tcp = 1;
>>                         break;
>>                 case ODP_IPPROTO_ICMP:
>> -                       pkt_hdr->proto_flags.icmp = 1;
>> +                       pkt_hdr->input_flags.icmp = 1;
>>                         break;
>>                 }
>>         }
>> diff --git a/platform/linux-generic/source/odp_packet_flags.c
>> b/platform/linux-generic/source/odp_packet_flags.c
>> new file mode 100644
>> index 0000000..0fd0aa9
>> --- /dev/null
>> +++ b/platform/linux-generic/source/odp_packet_flags.c
>> @@ -0,0 +1,116 @@
>> +/* Copyright (c) 2014, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> + #include <odp_packet_flags.h>
>> + #include <odp_packet_internal.h>
>> +
>> +
>> +int odp_packet_error(odp_packet_t pkt)
>> +{
>> +       return (odp_packet_hdr(pkt)->error_flags.all != 0);
>> +}
>> +
>> +/* Get Error Flags */
>> +
>> +int odp_packet_errflag_frame_len(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->error_flags.frame_len;
>> +}
>> +
>> +/* Get Input Flags */
>> +
>> +int odp_packet_inflag_l2(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.l2;
>> +}
>> +
>> +int odp_packet_inflag_l3(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.l3;
>> +}
>> +
>> +int odp_packet_inflag_l4(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.l4;
>> +}
>> +
>> +int odp_packet_inflag_eth(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.eth;
>> +}
>> +
>> +int odp_packet_inflag_jumbo(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.jumbo;
>> +}
>> +
>> +int odp_packet_inflag_vlan(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.vlan;
>> +}
>> +
>> +int odp_packet_inflag_vlan_qinq(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.vlan_qinq;
>> +}
>> +
>> +int odp_packet_inflag_arp(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.arp;
>> +}
>> +
>> +int odp_packet_inflag_ipv4(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.ipv4;
>> +}
>> +
>> +int odp_packet_inflag_ipv6(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.ipv6;
>> +}
>> +
>> +int odp_packet_inflag_ipfrag(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.ipfrag;
>> +}
>> +
>> +int odp_packet_inflag_ipopt(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.ipopt;
>> +}
>> +
>> +int odp_packet_inflag_ipsec(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.ipsec;
>> +}
>> +
>> +int odp_packet_inflag_udp(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.udp;
>> +}
>> +
>> +int odp_packet_inflag_tcp(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.tcp;
>> +}
>> +
>> +int odp_packet_inflag_sctp(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.sctp;
>> +}
>> +
>> +int odp_packet_inflag_icmp(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input_flags.icmp;
>> +}
>> +
>> +/* Set Output Flags */
>> +
>> +void odp_packet_outflag_l4_chksum(odp_packet_t pkt)
>> +{
>> +       odp_packet_hdr(pkt)->output_flags.l4_chksum = 1;
>> +}
>> +
>> --
>> 1.8.5.3
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "LNG ODP Sub-team - lng-odp@linaro.org" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to lng-odp+unsubscribe@linaro.org.
>> To post to this group, send email to lng-odp@linaro.org.
>> Visit this group at http://groups.google.com/a/linaro.org/group/lng-odp/.
>> To view this discussion on the web visit
>> https://groups.google.com/a/linaro.org/d/msgid/lng-odp/1392639281-2753-4-git-send-email-carl.wallen%40linaro.org
>> .
>> For more options, visit
>> https://groups.google.com/a/linaro.org/groups/opt_out.
>>
>
>  --
> You received this message because you are subscribed to the Google Groups
> "LNG ODP Sub-team - lng-odp@linaro.org" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to lng-odp+unsubscribe@linaro.org.
> To post to this group, send email to lng-odp@linaro.org.
> Visit this group at http://groups.google.com/a/linaro.org/group/lng-odp/.
> To view this discussion on the web visit
> https://groups.google.com/a/linaro.org/d/msgid/lng-odp/CAPiYAf5D0r941GnyhkuDEwqx%2BStLHOLHFTOfNOLdX8XpkK65PQ%40mail.gmail.com
> .
>
> For more options, visit
> https://groups.google.com/a/linaro.org/groups/opt_out.
>
Carl Wallen Feb. 18, 2014, 7:32 a.m. UTC | #3
On 17.2.2014 15:18, Ola Liljedahl wrote:
> odp_packet_flags.[ch]:
> Again too many functions which I don't think are necessary for ODP itself.
> So what's the reason for all of these functions? Do you think these are
> checks that might be HW-accelerated and thus deserve inclusion into ODP?

The thought was that these flags are potential candidates for HW
offload, i.e. HW pre-classification sets packet meta data that later can
be used by full scale flow classification or the application or even as
input to a fast-path networking stack.
So I see that these flags would be provided by the HW on a networking
SoC - should work at line rate.
I chose to have different access functions for each flag, because each
HW will probably offer packet meta data flags in very different formats.

> Regarding the implementation, is it the best choice to use a set of
> discrete bits? It is not a scalable approach as the number of supported
> protocols increase.

The implementation is totally internal to linux-generic and can be
changed if more protocols are needed. Eventually all this could be
handled by the HW. We should keep the number of protocols handled by
pre-classification to a minimum and let higher layer worry about others.

The thought was also that with the help of these flags & access
functions it would be easy and fast to decide if the packet should be
handled on the fast path or forwarded to the slow path for more
processing. E.g. if IP-option or IP-fragment flags are set then let slow
path deal with them directly etc.

> 
> On 17 February 2014 13:14, Carl Wallen <carl.wallen@linaro.org
> <mailto:carl.wallen@linaro.org>> wrote:
> 
>     Add ODP Packet Flags API funcs to access the error, input and output
>     flags set by packet IO.
> 
>     Signed-off-by: Carl Wallen <carl.wallen@linaro.org
>     <mailto:carl.wallen@linaro.org>>
>     ---
>      include/odp.h                                      |   1 +
>      include/odp_packet_flags.h                         | 189
>     +++++++++++++++++++++
>      platform/linux-generic/Makefile                    |   1 +
>      .../linux-generic/include/odp_packet_internal.h    |  95 ++++++++---
>      platform/linux-generic/source/odp_packet.c         |  18 +-
>      platform/linux-generic/source/odp_packet_flags.c   | 116 +++++++++++++
>      6 files changed, 383 insertions(+), 37 deletions(-)
>      create mode 100644 include/odp_packet_flags.h
>      create mode 100644 platform/linux-generic/source/odp_packet_flags.c
> 
>     diff --git a/include/odp.h b/include/odp.h
>     index 08c7c31..6a52346 100644
>     --- a/include/odp.h
>     +++ b/include/odp.h
>     @@ -295,6 +295,7 @@ extern "C" {
>      #include <odp_schedule.h>
>      #include <odp_sync.h>
>      #include <odp_packet.h>
>     +#include <odp_packet_flags.h>
>      #include <odp_packet_io.h>
> 
>      #ifdef __cplusplus
>     diff --git a/include/odp_packet_flags.h b/include/odp_packet_flags.h
>     new file mode 100644
>     index 0000000..eb9315b
>     --- /dev/null
>     +++ b/include/odp_packet_flags.h
>     @@ -0,0 +1,189 @@
>     +/* Copyright (c) 2014, Linaro Limited
>     + * All rights reserved.
>     + *
>     + * SPDX-License-Identifier:     BSD-3-Clause
>     + */
>     +
>     +
>     +/**
>     + * @file
>     + *
>     + * ODP packet flags
>     + */
>     +
>     +#ifndef ODP_PACKET_FLAGS_H_
>     +#define ODP_PACKET_FLAGS_H_
>     +
>     +#ifdef __cplusplus
>     +extern "C" {
>     +#endif
>     +
>     +#include <odp_std_types.h>
>     +#include <odp_packet.h>
>     +
>     +/**
>     + * Check for packet errors
>     + *
>     + * Checks all error flags at once.
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet has errors, 0 otherwise
>     + */
>     +int odp_packet_error(odp_packet_t pkt);
>     +
>     +/**
>     + * Check if error was 'frame length' error
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if frame length error detected, 0 otherwise
>     + */
>     +int odp_packet_errflag_frame_len(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for L2 header, e.g. ethernet
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains a valid & known L2 header, 0 otherwise
>     + */
>     +int odp_packet_inflag_l2(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for L3 header, e.g. IPv4, IPv6
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains a valid & known L3 header, 0 otherwise
>     + */
>     +int odp_packet_inflag_l3(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for L4 header, e.g. UDP, TCP, SCTP (also ICMP)
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains a valid & known L4 header, 0 otherwise
>     + */
>     +int odp_packet_inflag_l4(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for Ethernet header
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains a valid eth header, 0 otherwise
>     + */
>     +int odp_packet_inflag_eth(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for jumbo frame
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains jumbo frame, 0 otherwise
>     + */
>     +int odp_packet_inflag_jumbo(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for VLAN
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains a VLAN header, 0 otherwise
>     + */
>     +int odp_packet_inflag_vlan(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for VLAN QinQ (stacked VLAN)
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains a VLAN QinQ header, 0 otherwise
>     + */
>     +int odp_packet_inflag_vlan_qinq(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for ARP
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains an ARP header, 0 otherwise
>     + */
>     +int odp_packet_inflag_arp(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for IPv4
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains an IPv4 header, 0 otherwise
>     + */
>     +int odp_packet_inflag_ipv4(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for IPv6
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains an IPv6 header, 0 otherwise
>     + */
>     +int odp_packet_inflag_ipv6(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for IP fragment
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet is an IP fragment, 0 otherwise
>     + */
>     +int odp_packet_inflag_ipfrag(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for IP options
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains IP options, 0 otherwise
>     + */
>     +int odp_packet_inflag_ipopt(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for IPSec
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet requires IPSec processing, 0 otherwise
>     + */
>     +int odp_packet_inflag_ipsec(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for UDP
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains a UDP header, 0 otherwise
>     + */
>     +int odp_packet_inflag_udp(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for TCP
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains a TCP header, 0 otherwise
>     + */
>     +int odp_packet_inflag_tcp(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for SCTP
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains an SCTP header, 0 otherwise
>     + */
>     +int odp_packet_inflag_sctp(odp_packet_t pkt);
>     +
>     +/**
>     + * Check for ICMP
>     + *
>     + * @param pkt Packet handle
>     + * @return 1 if packet contains an ICMP header, 0 otherwise
>     + */
>     +int odp_packet_inflag_icmp(odp_packet_t pkt);
>     +
>     +/**
>     + * Request L4 checksum calculation
>     + *
>     + * @param pkt Packet handle
>     + */
>     +void odp_packet_outflag_l4_chksum(odp_packet_t pkt);
>     +
>     +#ifdef __cplusplus
>     +}
>     +#endif
>     +
>     +#endif
>     diff --git a/platform/linux-generic/Makefile
>     b/platform/linux-generic/Makefile
>     index f665683..b640928 100644
>     --- a/platform/linux-generic/Makefile
>     +++ b/platform/linux-generic/Makefile
>     @@ -54,6 +54,7 @@ OBJS    += $(OBJ_DIR)/odp_coremask.o
>      OBJS    += $(OBJ_DIR)/odp_init.o
>      OBJS    += $(OBJ_DIR)/odp_linux.o
>      OBJS    += $(OBJ_DIR)/odp_packet.o
>     +OBJS    += $(OBJ_DIR)/odp_packet_flags.o
>      OBJS    += $(OBJ_DIR)/odp_packet_io.o
>      OBJS    += $(OBJ_DIR)/odp_packet_socket.o
>      OBJS    += $(OBJ_DIR)/odp_queue.o
>     diff --git a/platform/linux-generic/include/odp_packet_internal.h
>     b/platform/linux-generic/include/odp_packet_internal.h
>     index afef976..f0dda95 100644
>     --- a/platform/linux-generic/include/odp_packet_internal.h
>     +++ b/platform/linux-generic/include/odp_packet_internal.h
>     @@ -25,59 +25,98 @@ extern "C" {
>      #include <odp_packet.h>
>      #include <odp_packet_io.h>
> 
>     -typedef struct {
>     -       uint32_t l2:1;
>     -       uint32_t l3:1;
>     -       uint32_t l4:1;
>     -
>     -       uint32_t macsec:1;
>     -       uint32_t vlan:1;
>     -       uint32_t vlan_double:1;
>     -       uint32_t ipv4:1;
>     -       uint32_t ipv6:1;
>     -       uint32_t ip_frag:1;
>     -       uint32_t udp:1;
>     -       uint32_t tcp:1;
>     -       uint32_t icmp:1;
>     -} proto_flags_t;
>     +/**
>     + * Packet input & protocol flags
>     + */
>     +typedef union {
>     +       /* All input flags */
>     +       uint32_t all;
> 
>     -typedef struct {
>     -       uint32_t frame_len:1;
>     -       uint32_t l2_chksum:1;
>     -       uint32_t ip_err:1;
>     -       uint32_t tcp_err:1;
>     -       uint32_t udp_err:1;
>     +       /* Bitfield flags for each protocol */
>     +       uint32_t l2:1;        /**< known L2 protocol present */
>     +       uint32_t l3:1;        /**< known L3 protocol present */
>     +       uint32_t l4:1;        /**< known L4 protocol present */
>     +
>     +       uint32_t eth:1;       /**< Ethernet */
>     +       uint32_t jumbo:1;     /**< Jumbo frame */
>     +       uint32_t vlan:1;      /**< VLAN hdr found */
>     +       uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */
>     +
>     +       uint32_t arp:1;       /**< ARP */
>     +
>     +       uint32_t ipv4:1;      /**< IPv4 */
>     +       uint32_t ipv6:1;      /**< IPv6 */
>     +       uint32_t ipfrag:1;    /**< IP fragment */
>     +       uint32_t ipopt:1;     /**< IP optional headers */
>     +       uint32_t ipsec;       /**< IPSec decryption may be needed */
>     +
>     +       uint32_t udp:1;       /**< UDP */
>     +       uint32_t tcp:1;       /**< TCP */
>     +       uint32_t sctp:1;      /**< SCTP */
>     +       uint32_t icmp:1;      /**< ICMP */
>     +} input_flags_t;
>     +
>     +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t),
>     INPUT_FLAGS_SIZE_ERROR);
>     +
>     +/**
>     + * Packet error flags
>     + */
>     +typedef union {
>     +       /* All error flags */
>     +       uint32_t all;
>     +
>     +       /* Bitfield flags for each detected error */
>     +       uint32_t frame_len:1; /**< Frame length error */
>     +       uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD */
>     +       uint32_t ip_err:1;    /**< IP error,  checks TBD */
>     +       uint32_t tcp_err:1;   /**< TCP error, checks TBD */
>     +       uint32_t udp_err:1;   /**< UDP error, checks TBD */
>      } error_flags_t;
> 
>     -typedef struct {
>     -       uint32_t calc_l4_chksum:1;
>     +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t),
>     ERROR_FLAGS_SIZE_ERROR);
>     +
>     +/**
>     + * Packet output flags
>     + */
>     +typedef union {
>     +       /* All output flags */
>     +       uint32_t all;
>     +
>     +       /* Bitfield flags for each output option */
>     +       uint32_t l4_chksum:1; /**< Request L4 checksum calculation */
>      } output_flags_t;
> 
>     +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t),
>     OUTPUT_FLAGS_SIZE_ERROR);
>     +
>      /**
>       * Internal Packet header
>       */
>     -typedef struct odp_packet_hdr_t {
>     +typedef struct {
>             /* common buffer header */
>             odp_buffer_hdr_t buf_hdr;
> 
>     -       proto_flags_t  proto_flags;
>     +       input_flags_t  input_flags;
>             error_flags_t  error_flags;
>             output_flags_t output_flags;
> 
>     -       uint32_t l2_offset;
>     -       uint32_t l3_offset;
>     -       uint32_t l4_offset;
>     +       uint32_t frame_offset; /**< offset to start of frame, even
>     on error */
>     +       uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */
>     +       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 frame_len;
> 
>             odp_pktio_t input;
> 
>     +       uint32_t pad;
>             uint8_t payload[];
> 
>      } odp_packet_hdr_t;
> 
>      ODP_ASSERT(sizeof(odp_packet_hdr_t) ==
>     ODP_OFFSETOF(odp_packet_hdr_t, payload),
>                ODP_PACKET_HDR_T__SIZE_ERR);
>     +ODP_ASSERT(sizeof(odp_packet_hdr_t) % sizeof(uint64_t) == 0,
>     +          ODP_PACKET_HDR_T__SIZE_ERR2);
> 
>      /**
>       * Return the packet header
>     diff --git a/platform/linux-generic/source/odp_packet.c
>     b/platform/linux-generic/source/odp_packet.c
>     index 6b06f76..6ee2c5b 100644
>     --- a/platform/linux-generic/source/odp_packet.c
>     +++ b/platform/linux-generic/source/odp_packet.c
>     @@ -124,7 +124,7 @@ void odp_packet_parse(odp_packet_t pkt, size_t
>     len, size_t l2_offset)
>             if (odp_unlikely(len < ODP_ETH_LEN_MIN))
>                     pkt_hdr->error_flags.frame_len = 1;
> 
>     -       pkt_hdr->proto_flags.l2 = 1;
>     +       pkt_hdr->input_flags.l2 = 1;
>             pkt_hdr->l2_offset = l2_offset;
>             eth = (odp_ethhdr_t *)odp_packet_l2(pkt);
> 
>     @@ -132,25 +132,25 @@ void odp_packet_parse(odp_packet_t pkt, size_t
>     len, size_t l2_offset)
>             vlan = (odp_vlanhdr_t *)&eth->type;
> 
>             if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
>     -               pkt_hdr->proto_flags.vlan_double = 1;
>     +               pkt_hdr->input_flags.vlan_qinq = 1;
>                     ethtype = odp_be_to_cpu_16(vlan->tpid);
>                     offset += sizeof(odp_vlanhdr_t);
>                     vlan = &vlan[1];
>             }
> 
>             if (ethtype == ODP_ETHTYPE_VLAN) {
>     -               pkt_hdr->proto_flags.vlan = 1;
>     +               pkt_hdr->input_flags.vlan = 1;
>                     ethtype = odp_be_to_cpu_16(vlan->tpid);
>                     offset += sizeof(odp_vlanhdr_t);
>             }
> 
>     -       pkt_hdr->proto_flags.l3 = 1;
>     +       pkt_hdr->input_flags.l3 = 1;
>             pkt_hdr->l3_offset = l2_offset + ODP_ETHHDR_LEN + offset;
> 
>             if (ethtype == ODP_ETHTYPE_IPV4) {
>                     uint8_t ihl;
> 
>     -               pkt_hdr->proto_flags.ipv4 = 1;
>     +               pkt_hdr->input_flags.ipv4 = 1;
>                     ip = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
> 
>                     ihl = ODP_IPV4HDR_IHL(ip->ver_ihl);
>     @@ -159,19 +159,19 @@ void odp_packet_parse(odp_packet_t pkt, size_t
>     len, size_t l2_offset)
>                             return;
>                     }
> 
>     -               pkt_hdr->proto_flags.l4 = 1;
>     +               pkt_hdr->input_flags.l4 = 1;
>                     pkt_hdr->l4_offset = pkt_hdr->l3_offset +
>                                          sizeof(uint32_t) * ihl;
> 
>                     switch (ip->proto) {
>                     case ODP_IPPROTO_UDP:
>     -                       pkt_hdr->proto_flags.udp = 1;
>     +                       pkt_hdr->input_flags.udp = 1;
>                             break;
>                     case ODP_IPPROTO_TCP:
>     -                       pkt_hdr->proto_flags.tcp = 1;
>     +                       pkt_hdr->input_flags.tcp = 1;
>                             break;
>                     case ODP_IPPROTO_ICMP:
>     -                       pkt_hdr->proto_flags.icmp = 1;
>     +                       pkt_hdr->input_flags.icmp = 1;
>                             break;
>                     }
>             }
>     diff --git a/platform/linux-generic/source/odp_packet_flags.c
>     b/platform/linux-generic/source/odp_packet_flags.c
>     new file mode 100644
>     index 0000000..0fd0aa9
>     --- /dev/null
>     +++ b/platform/linux-generic/source/odp_packet_flags.c
>     @@ -0,0 +1,116 @@
>     +/* Copyright (c) 2014, Linaro Limited
>     + * All rights reserved.
>     + *
>     + * SPDX-License-Identifier:     BSD-3-Clause
>     + */
>     +
>     + #include <odp_packet_flags.h>
>     + #include <odp_packet_internal.h>
>     +
>     +
>     +int odp_packet_error(odp_packet_t pkt)
>     +{
>     +       return (odp_packet_hdr(pkt)->error_flags.all != 0);
>     +}
>     +
>     +/* Get Error Flags */
>     +
>     +int odp_packet_errflag_frame_len(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->error_flags.frame_len;
>     +}
>     +
>     +/* Get Input Flags */
>     +
>     +int odp_packet_inflag_l2(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.l2;
>     +}
>     +
>     +int odp_packet_inflag_l3(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.l3;
>     +}
>     +
>     +int odp_packet_inflag_l4(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.l4;
>     +}
>     +
>     +int odp_packet_inflag_eth(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.eth;
>     +}
>     +
>     +int odp_packet_inflag_jumbo(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.jumbo;
>     +}
>     +
>     +int odp_packet_inflag_vlan(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.vlan;
>     +}
>     +
>     +int odp_packet_inflag_vlan_qinq(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.vlan_qinq;
>     +}
>     +
>     +int odp_packet_inflag_arp(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.arp;
>     +}
>     +
>     +int odp_packet_inflag_ipv4(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.ipv4;
>     +}
>     +
>     +int odp_packet_inflag_ipv6(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.ipv6;
>     +}
>     +
>     +int odp_packet_inflag_ipfrag(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.ipfrag;
>     +}
>     +
>     +int odp_packet_inflag_ipopt(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.ipopt;
>     +}
>     +
>     +int odp_packet_inflag_ipsec(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.ipsec;
>     +}
>     +
>     +int odp_packet_inflag_udp(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.udp;
>     +}
>     +
>     +int odp_packet_inflag_tcp(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.tcp;
>     +}
>     +
>     +int odp_packet_inflag_sctp(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.sctp;
>     +}
>     +
>     +int odp_packet_inflag_icmp(odp_packet_t pkt)
>     +{
>     +       return odp_packet_hdr(pkt)->input_flags.icmp;
>     +}
>     +
>     +/* Set Output Flags */
>     +
>     +void odp_packet_outflag_l4_chksum(odp_packet_t pkt)
>     +{
>     +       odp_packet_hdr(pkt)->output_flags.l4_chksum = 1;
>     +}
>     +
>     --
>     1.8.5.3
> 
>     --
>     You received this message because you are subscribed to the Google
>     Groups "LNG ODP Sub-team - lng-odp@linaro.org
>     <mailto:lng-odp@linaro.org>" group.
>     To unsubscribe from this group and stop receiving emails from it,
>     send an email to lng-odp+unsubscribe@linaro.org
>     <mailto:lng-odp%2Bunsubscribe@linaro.org>.
>     To post to this group, send email to lng-odp@linaro.org
>     <mailto:lng-odp@linaro.org>.
>     Visit this group at
>     http://groups.google.com/a/linaro.org/group/lng-odp/.
>     To view this discussion on the web visit
>     https://groups.google.com/a/linaro.org/d/msgid/lng-odp/1392639281-2753-4-git-send-email-carl.wallen%40linaro.org.
>     For more options, visit
>     https://groups.google.com/a/linaro.org/groups/opt_out.
> 
>
Ola Liljedahl Feb. 21, 2014, 10:17 a.m. UTC | #4
Even if ODP for linux-generic is not supposed to be a speed demon, we don't
have to give away performance. That's why I am concerned about performance
also for his software-based implementation. Checking for too many protocol
types and setting type different bits (why not using an enumeration?) in
the packet header seems not very optimal (lots of checks for each packet
whose results in practice will not be used => unnecessary overhead). The IP
header already has the IP protocol enumeration, what else is needed for
protocol demultiplexing? I would prefer a flag/function that told me
whether the packet contains a valid IPv4 header (i.e. frametype is IPv4,
header checksum is correct and IP.total_len is also valid), some or all of
these checks are often performed by the HW.

Also defining this API may create expectations that also HW-based
implementations should provide these functions, even if HW does not support
this type of classification. Indeed do we not envision classification to
distribute packets of different types and protocols to different (sets of)
queues? Then the application (especially if it is using execution objects)
will not have to check for protocol type at all.


On 18 February 2014 07:32, Carl Wallen <carl.wallen@linaro.org> wrote:

> On 17.2.2014 15:18, Ola Liljedahl wrote:
> > odp_packet_flags.[ch]:
> > Again too many functions which I don't think are necessary for ODP
> itself.
> > So what's the reason for all of these functions? Do you think these are
> > checks that might be HW-accelerated and thus deserve inclusion into ODP?
>
> The thought was that these flags are potential candidates for HW
> offload, i.e. HW pre-classification sets packet meta data that later can
> be used by full scale flow classification or the application or even as
> input to a fast-path networking stack.
> So I see that these flags would be provided by the HW on a networking
> SoC - should work at line rate.
> I chose to have different access functions for each flag, because each
> HW will probably offer packet meta data flags in very different formats.
>
> > Regarding the implementation, is it the best choice to use a set of
> > discrete bits? It is not a scalable approach as the number of supported
> > protocols increase.
>
> The implementation is totally internal to linux-generic and can be
> changed if more protocols are needed. Eventually all this could be
> handled by the HW. We should keep the number of protocols handled by
> pre-classification to a minimum and let higher layer worry about others.
>
> The thought was also that with the help of these flags & access
> functions it would be easy and fast to decide if the packet should be
> handled on the fast path or forwarded to the slow path for more
> processing. E.g. if IP-option or IP-fragment flags are set then let slow
> path deal with them directly etc.
>
> >
> > On 17 February 2014 13:14, Carl Wallen <carl.wallen@linaro.org
> > <mailto:carl.wallen@linaro.org>> wrote:
> >
> >     Add ODP Packet Flags API funcs to access the error, input and output
> >     flags set by packet IO.
> >
> >     Signed-off-by: Carl Wallen <carl.wallen@linaro.org
> >     <mailto:carl.wallen@linaro.org>>
> >     ---
> >      include/odp.h                                      |   1 +
> >      include/odp_packet_flags.h                         | 189
> >     +++++++++++++++++++++
> >      platform/linux-generic/Makefile                    |   1 +
> >      .../linux-generic/include/odp_packet_internal.h    |  95 ++++++++---
> >      platform/linux-generic/source/odp_packet.c         |  18 +-
> >      platform/linux-generic/source/odp_packet_flags.c   | 116
> +++++++++++++
> >      6 files changed, 383 insertions(+), 37 deletions(-)
> >      create mode 100644 include/odp_packet_flags.h
> >      create mode 100644 platform/linux-generic/source/odp_packet_flags.c
> >
> >     diff --git a/include/odp.h b/include/odp.h
> >     index 08c7c31..6a52346 100644
> >     --- a/include/odp.h
> >     +++ b/include/odp.h
> >     @@ -295,6 +295,7 @@ extern "C" {
> >      #include <odp_schedule.h>
> >      #include <odp_sync.h>
> >      #include <odp_packet.h>
> >     +#include <odp_packet_flags.h>
> >      #include <odp_packet_io.h>
> >
> >      #ifdef __cplusplus
> >     diff --git a/include/odp_packet_flags.h b/include/odp_packet_flags.h
> >     new file mode 100644
> >     index 0000000..eb9315b
> >     --- /dev/null
> >     +++ b/include/odp_packet_flags.h
> >     @@ -0,0 +1,189 @@
> >     +/* Copyright (c) 2014, Linaro Limited
> >     + * All rights reserved.
> >     + *
> >     + * SPDX-License-Identifier:     BSD-3-Clause
> >     + */
> >     +
> >     +
> >     +/**
> >     + * @file
> >     + *
> >     + * ODP packet flags
> >     + */
> >     +
> >     +#ifndef ODP_PACKET_FLAGS_H_
> >     +#define ODP_PACKET_FLAGS_H_
> >     +
> >     +#ifdef __cplusplus
> >     +extern "C" {
> >     +#endif
> >     +
> >     +#include <odp_std_types.h>
> >     +#include <odp_packet.h>
> >     +
> >     +/**
> >     + * Check for packet errors
> >     + *
> >     + * Checks all error flags at once.
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet has errors, 0 otherwise
> >     + */
> >     +int odp_packet_error(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check if error was 'frame length' error
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if frame length error detected, 0 otherwise
> >     + */
> >     +int odp_packet_errflag_frame_len(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for L2 header, e.g. ethernet
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains a valid & known L2 header, 0
> otherwise
> >     + */
> >     +int odp_packet_inflag_l2(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for L3 header, e.g. IPv4, IPv6
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains a valid & known L3 header, 0
> otherwise
> >     + */
> >     +int odp_packet_inflag_l3(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for L4 header, e.g. UDP, TCP, SCTP (also ICMP)
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains a valid & known L4 header, 0
> otherwise
> >     + */
> >     +int odp_packet_inflag_l4(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for Ethernet header
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains a valid eth header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_eth(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for jumbo frame
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains jumbo frame, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_jumbo(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for VLAN
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains a VLAN header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_vlan(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for VLAN QinQ (stacked VLAN)
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains a VLAN QinQ header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_vlan_qinq(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for ARP
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains an ARP header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_arp(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for IPv4
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains an IPv4 header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_ipv4(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for IPv6
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains an IPv6 header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_ipv6(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for IP fragment
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet is an IP fragment, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_ipfrag(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for IP options
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains IP options, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_ipopt(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for IPSec
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet requires IPSec processing, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_ipsec(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for UDP
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains a UDP header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_udp(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for TCP
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains a TCP header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_tcp(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for SCTP
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains an SCTP header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_sctp(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Check for ICMP
> >     + *
> >     + * @param pkt Packet handle
> >     + * @return 1 if packet contains an ICMP header, 0 otherwise
> >     + */
> >     +int odp_packet_inflag_icmp(odp_packet_t pkt);
> >     +
> >     +/**
> >     + * Request L4 checksum calculation
> >     + *
> >     + * @param pkt Packet handle
> >     + */
> >     +void odp_packet_outflag_l4_chksum(odp_packet_t pkt);
> >     +
> >     +#ifdef __cplusplus
> >     +}
> >     +#endif
> >     +
> >     +#endif
> >     diff --git a/platform/linux-generic/Makefile
> >     b/platform/linux-generic/Makefile
> >     index f665683..b640928 100644
> >     --- a/platform/linux-generic/Makefile
> >     +++ b/platform/linux-generic/Makefile
> >     @@ -54,6 +54,7 @@ OBJS    += $(OBJ_DIR)/odp_coremask.o
> >      OBJS    += $(OBJ_DIR)/odp_init.o
> >      OBJS    += $(OBJ_DIR)/odp_linux.o
> >      OBJS    += $(OBJ_DIR)/odp_packet.o
> >     +OBJS    += $(OBJ_DIR)/odp_packet_flags.o
> >      OBJS    += $(OBJ_DIR)/odp_packet_io.o
> >      OBJS    += $(OBJ_DIR)/odp_packet_socket.o
> >      OBJS    += $(OBJ_DIR)/odp_queue.o
> >     diff --git a/platform/linux-generic/include/odp_packet_internal.h
> >     b/platform/linux-generic/include/odp_packet_internal.h
> >     index afef976..f0dda95 100644
> >     --- a/platform/linux-generic/include/odp_packet_internal.h
> >     +++ b/platform/linux-generic/include/odp_packet_internal.h
> >     @@ -25,59 +25,98 @@ extern "C" {
> >      #include <odp_packet.h>
> >      #include <odp_packet_io.h>
> >
> >     -typedef struct {
> >     -       uint32_t l2:1;
> >     -       uint32_t l3:1;
> >     -       uint32_t l4:1;
> >     -
> >     -       uint32_t macsec:1;
> >     -       uint32_t vlan:1;
> >     -       uint32_t vlan_double:1;
> >     -       uint32_t ipv4:1;
> >     -       uint32_t ipv6:1;
> >     -       uint32_t ip_frag:1;
> >     -       uint32_t udp:1;
> >     -       uint32_t tcp:1;
> >     -       uint32_t icmp:1;
> >     -} proto_flags_t;
> >     +/**
> >     + * Packet input & protocol flags
> >     + */
> >     +typedef union {
> >     +       /* All input flags */
> >     +       uint32_t all;
> >
> >     -typedef struct {
> >     -       uint32_t frame_len:1;
> >     -       uint32_t l2_chksum:1;
> >     -       uint32_t ip_err:1;
> >     -       uint32_t tcp_err:1;
> >     -       uint32_t udp_err:1;
> >     +       /* Bitfield flags for each protocol */
> >     +       uint32_t l2:1;        /**< known L2 protocol present */
> >     +       uint32_t l3:1;        /**< known L3 protocol present */
> >     +       uint32_t l4:1;        /**< known L4 protocol present */
> >     +
> >     +       uint32_t eth:1;       /**< Ethernet */
> >     +       uint32_t jumbo:1;     /**< Jumbo frame */
> >     +       uint32_t vlan:1;      /**< VLAN hdr found */
> >     +       uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */
> >     +
> >     +       uint32_t arp:1;       /**< ARP */
> >     +
> >     +       uint32_t ipv4:1;      /**< IPv4 */
> >     +       uint32_t ipv6:1;      /**< IPv6 */
> >     +       uint32_t ipfrag:1;    /**< IP fragment */
> >     +       uint32_t ipopt:1;     /**< IP optional headers */
> >     +       uint32_t ipsec;       /**< IPSec decryption may be needed */
> >     +
> >     +       uint32_t udp:1;       /**< UDP */
> >     +       uint32_t tcp:1;       /**< TCP */
> >     +       uint32_t sctp:1;      /**< SCTP */
> >     +       uint32_t icmp:1;      /**< ICMP */
> >     +} input_flags_t;
> >     +
> >     +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t),
> >     INPUT_FLAGS_SIZE_ERROR);
> >     +
> >     +/**
> >     + * Packet error flags
> >     + */
> >     +typedef union {
> >     +       /* All error flags */
> >     +       uint32_t all;
> >     +
> >     +       /* Bitfield flags for each detected error */
> >     +       uint32_t frame_len:1; /**< Frame length error */
> >     +       uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD */
> >     +       uint32_t ip_err:1;    /**< IP error,  checks TBD */
> >     +       uint32_t tcp_err:1;   /**< TCP error, checks TBD */
> >     +       uint32_t udp_err:1;   /**< UDP error, checks TBD */
> >      } error_flags_t;
> >
> >     -typedef struct {
> >     -       uint32_t calc_l4_chksum:1;
> >     +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t),
> >     ERROR_FLAGS_SIZE_ERROR);
> >     +
> >     +/**
> >     + * Packet output flags
> >     + */
> >     +typedef union {
> >     +       /* All output flags */
> >     +       uint32_t all;
> >     +
> >     +       /* Bitfield flags for each output option */
> >     +       uint32_t l4_chksum:1; /**< Request L4 checksum calculation */
> >      } output_flags_t;
> >
> >     +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t),
> >     OUTPUT_FLAGS_SIZE_ERROR);
> >     +
> >      /**
> >       * Internal Packet header
> >       */
> >     -typedef struct odp_packet_hdr_t {
> >     +typedef struct {
> >             /* common buffer header */
> >             odp_buffer_hdr_t buf_hdr;
> >
> >     -       proto_flags_t  proto_flags;
> >     +       input_flags_t  input_flags;
> >             error_flags_t  error_flags;
> >             output_flags_t output_flags;
> >
> >     -       uint32_t l2_offset;
> >     -       uint32_t l3_offset;
> >     -       uint32_t l4_offset;
> >     +       uint32_t frame_offset; /**< offset to start of frame, even
> >     on error */
> >     +       uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */
> >     +       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 frame_len;
> >
> >             odp_pktio_t input;
> >
> >     +       uint32_t pad;
> >             uint8_t payload[];
> >
> >      } odp_packet_hdr_t;
> >
> >      ODP_ASSERT(sizeof(odp_packet_hdr_t) ==
> >     ODP_OFFSETOF(odp_packet_hdr_t, payload),
> >                ODP_PACKET_HDR_T__SIZE_ERR);
> >     +ODP_ASSERT(sizeof(odp_packet_hdr_t) % sizeof(uint64_t) == 0,
> >     +          ODP_PACKET_HDR_T__SIZE_ERR2);
> >
> >      /**
> >       * Return the packet header
> >     diff --git a/platform/linux-generic/source/odp_packet.c
> >     b/platform/linux-generic/source/odp_packet.c
> >     index 6b06f76..6ee2c5b 100644
> >     --- a/platform/linux-generic/source/odp_packet.c
> >     +++ b/platform/linux-generic/source/odp_packet.c
> >     @@ -124,7 +124,7 @@ void odp_packet_parse(odp_packet_t pkt, size_t
> >     len, size_t l2_offset)
> >             if (odp_unlikely(len < ODP_ETH_LEN_MIN))
> >                     pkt_hdr->error_flags.frame_len = 1;
> >
> >     -       pkt_hdr->proto_flags.l2 = 1;
> >     +       pkt_hdr->input_flags.l2 = 1;
> >             pkt_hdr->l2_offset = l2_offset;
> >             eth = (odp_ethhdr_t *)odp_packet_l2(pkt);
> >
> >     @@ -132,25 +132,25 @@ void odp_packet_parse(odp_packet_t pkt, size_t
> >     len, size_t l2_offset)
> >             vlan = (odp_vlanhdr_t *)&eth->type;
> >
> >             if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
> >     -               pkt_hdr->proto_flags.vlan_double = 1;
> >     +               pkt_hdr->input_flags.vlan_qinq = 1;
> >                     ethtype = odp_be_to_cpu_16(vlan->tpid);
> >                     offset += sizeof(odp_vlanhdr_t);
> >                     vlan = &vlan[1];
> >             }
> >
> >             if (ethtype == ODP_ETHTYPE_VLAN) {
> >     -               pkt_hdr->proto_flags.vlan = 1;
> >     +               pkt_hdr->input_flags.vlan = 1;
> >                     ethtype = odp_be_to_cpu_16(vlan->tpid);
> >                     offset += sizeof(odp_vlanhdr_t);
> >             }
> >
> >     -       pkt_hdr->proto_flags.l3 = 1;
> >     +       pkt_hdr->input_flags.l3 = 1;
> >             pkt_hdr->l3_offset = l2_offset + ODP_ETHHDR_LEN + offset;
> >
> >             if (ethtype == ODP_ETHTYPE_IPV4) {
> >                     uint8_t ihl;
> >
> >     -               pkt_hdr->proto_flags.ipv4 = 1;
> >     +               pkt_hdr->input_flags.ipv4 = 1;
> >                     ip = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
> >
> >                     ihl = ODP_IPV4HDR_IHL(ip->ver_ihl);
> >     @@ -159,19 +159,19 @@ void odp_packet_parse(odp_packet_t pkt, size_t
> >     len, size_t l2_offset)
> >                             return;
> >                     }
> >
> >     -               pkt_hdr->proto_flags.l4 = 1;
> >     +               pkt_hdr->input_flags.l4 = 1;
> >                     pkt_hdr->l4_offset = pkt_hdr->l3_offset +
> >                                          sizeof(uint32_t) * ihl;
> >
> >                     switch (ip->proto) {
> >                     case ODP_IPPROTO_UDP:
> >     -                       pkt_hdr->proto_flags.udp = 1;
> >     +                       pkt_hdr->input_flags.udp = 1;
> >                             break;
> >                     case ODP_IPPROTO_TCP:
> >     -                       pkt_hdr->proto_flags.tcp = 1;
> >     +                       pkt_hdr->input_flags.tcp = 1;
> >                             break;
> >                     case ODP_IPPROTO_ICMP:
> >     -                       pkt_hdr->proto_flags.icmp = 1;
> >     +                       pkt_hdr->input_flags.icmp = 1;
> >                             break;
> >                     }
> >             }
> >     diff --git a/platform/linux-generic/source/odp_packet_flags.c
> >     b/platform/linux-generic/source/odp_packet_flags.c
> >     new file mode 100644
> >     index 0000000..0fd0aa9
> >     --- /dev/null
> >     +++ b/platform/linux-generic/source/odp_packet_flags.c
> >     @@ -0,0 +1,116 @@
> >     +/* Copyright (c) 2014, Linaro Limited
> >     + * All rights reserved.
> >     + *
> >     + * SPDX-License-Identifier:     BSD-3-Clause
> >     + */
> >     +
> >     + #include <odp_packet_flags.h>
> >     + #include <odp_packet_internal.h>
> >     +
> >     +
> >     +int odp_packet_error(odp_packet_t pkt)
> >     +{
> >     +       return (odp_packet_hdr(pkt)->error_flags.all != 0);
> >     +}
> >     +
> >     +/* Get Error Flags */
> >     +
> >     +int odp_packet_errflag_frame_len(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->error_flags.frame_len;
> >     +}
> >     +
> >     +/* Get Input Flags */
> >     +
> >     +int odp_packet_inflag_l2(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.l2;
> >     +}
> >     +
> >     +int odp_packet_inflag_l3(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.l3;
> >     +}
> >     +
> >     +int odp_packet_inflag_l4(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.l4;
> >     +}
> >     +
> >     +int odp_packet_inflag_eth(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.eth;
> >     +}
> >     +
> >     +int odp_packet_inflag_jumbo(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.jumbo;
> >     +}
> >     +
> >     +int odp_packet_inflag_vlan(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.vlan;
> >     +}
> >     +
> >     +int odp_packet_inflag_vlan_qinq(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.vlan_qinq;
> >     +}
> >     +
> >     +int odp_packet_inflag_arp(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.arp;
> >     +}
> >     +
> >     +int odp_packet_inflag_ipv4(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.ipv4;
> >     +}
> >     +
> >     +int odp_packet_inflag_ipv6(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.ipv6;
> >     +}
> >     +
> >     +int odp_packet_inflag_ipfrag(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.ipfrag;
> >     +}
> >     +
> >     +int odp_packet_inflag_ipopt(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.ipopt;
> >     +}
> >     +
> >     +int odp_packet_inflag_ipsec(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.ipsec;
> >     +}
> >     +
> >     +int odp_packet_inflag_udp(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.udp;
> >     +}
> >     +
> >     +int odp_packet_inflag_tcp(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.tcp;
> >     +}
> >     +
> >     +int odp_packet_inflag_sctp(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.sctp;
> >     +}
> >     +
> >     +int odp_packet_inflag_icmp(odp_packet_t pkt)
> >     +{
> >     +       return odp_packet_hdr(pkt)->input_flags.icmp;
> >     +}
> >     +
> >     +/* Set Output Flags */
> >     +
> >     +void odp_packet_outflag_l4_chksum(odp_packet_t pkt)
> >     +{
> >     +       odp_packet_hdr(pkt)->output_flags.l4_chksum = 1;
> >     +}
> >     +
> >     --
> >     1.8.5.3
> >
> >     --
> >     You received this message because you are subscribed to the Google
> >     Groups "LNG ODP Sub-team - lng-odp@linaro.org
> >     <mailto:lng-odp@linaro.org>" group.
> >     To unsubscribe from this group and stop receiving emails from it,
> >     send an email to lng-odp+unsubscribe@linaro.org
> >     <mailto:lng-odp%2Bunsubscribe@linaro.org>.
> >     To post to this group, send email to lng-odp@linaro.org
> >     <mailto:lng-odp@linaro.org>.
> >     Visit this group at
> >     http://groups.google.com/a/linaro.org/group/lng-odp/.
> >     To view this discussion on the web visit
> >
> https://groups.google.com/a/linaro.org/d/msgid/lng-odp/1392639281-2753-4-git-send-email-carl.wallen%40linaro.org
> .
> >     For more options, visit
> >     https://groups.google.com/a/linaro.org/groups/opt_out.
> >
> >
>
>
diff mbox

Patch

diff --git a/include/odp.h b/include/odp.h
index 08c7c31..6a52346 100644
--- a/include/odp.h
+++ b/include/odp.h
@@ -295,6 +295,7 @@  extern "C" {
 #include <odp_schedule.h>
 #include <odp_sync.h>
 #include <odp_packet.h>
+#include <odp_packet_flags.h>
 #include <odp_packet_io.h>
 
 #ifdef __cplusplus
diff --git a/include/odp_packet_flags.h b/include/odp_packet_flags.h
new file mode 100644
index 0000000..eb9315b
--- /dev/null
+++ b/include/odp_packet_flags.h
@@ -0,0 +1,189 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP packet flags
+ */
+
+#ifndef ODP_PACKET_FLAGS_H_
+#define ODP_PACKET_FLAGS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_std_types.h>
+#include <odp_packet.h>
+
+/**
+ * Check for packet errors
+ *
+ * Checks all error flags at once.
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet has errors, 0 otherwise
+ */
+int odp_packet_error(odp_packet_t pkt);
+
+/**
+ * Check if error was 'frame length' error
+ *
+ * @param pkt Packet handle
+ * @return 1 if frame length error detected, 0 otherwise
+ */
+int odp_packet_errflag_frame_len(odp_packet_t pkt);
+
+/**
+ * Check for L2 header, e.g. ethernet
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains a valid & known L2 header, 0 otherwise
+ */
+int odp_packet_inflag_l2(odp_packet_t pkt);
+
+/**
+ * Check for L3 header, e.g. IPv4, IPv6
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains a valid & known L3 header, 0 otherwise
+ */
+int odp_packet_inflag_l3(odp_packet_t pkt);
+
+/**
+ * Check for L4 header, e.g. UDP, TCP, SCTP (also ICMP)
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains a valid & known L4 header, 0 otherwise
+ */
+int odp_packet_inflag_l4(odp_packet_t pkt);
+
+/**
+ * Check for Ethernet header
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains a valid eth header, 0 otherwise
+ */
+int odp_packet_inflag_eth(odp_packet_t pkt);
+
+/**
+ * Check for jumbo frame
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains jumbo frame, 0 otherwise
+ */
+int odp_packet_inflag_jumbo(odp_packet_t pkt);
+
+/**
+ * Check for VLAN
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains a VLAN header, 0 otherwise
+ */
+int odp_packet_inflag_vlan(odp_packet_t pkt);
+
+/**
+ * Check for VLAN QinQ (stacked VLAN)
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains a VLAN QinQ header, 0 otherwise
+ */
+int odp_packet_inflag_vlan_qinq(odp_packet_t pkt);
+
+/**
+ * Check for ARP
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains an ARP header, 0 otherwise
+ */
+int odp_packet_inflag_arp(odp_packet_t pkt);
+
+/**
+ * Check for IPv4
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains an IPv4 header, 0 otherwise
+ */
+int odp_packet_inflag_ipv4(odp_packet_t pkt);
+
+/**
+ * Check for IPv6
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains an IPv6 header, 0 otherwise
+ */
+int odp_packet_inflag_ipv6(odp_packet_t pkt);
+
+/**
+ * Check for IP fragment
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet is an IP fragment, 0 otherwise
+ */
+int odp_packet_inflag_ipfrag(odp_packet_t pkt);
+
+/**
+ * Check for IP options
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains IP options, 0 otherwise
+ */
+int odp_packet_inflag_ipopt(odp_packet_t pkt);
+
+/**
+ * Check for IPSec
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet requires IPSec processing, 0 otherwise
+ */
+int odp_packet_inflag_ipsec(odp_packet_t pkt);
+
+/**
+ * Check for UDP
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains a UDP header, 0 otherwise
+ */
+int odp_packet_inflag_udp(odp_packet_t pkt);
+
+/**
+ * Check for TCP
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains a TCP header, 0 otherwise
+ */
+int odp_packet_inflag_tcp(odp_packet_t pkt);
+
+/**
+ * Check for SCTP
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains an SCTP header, 0 otherwise
+ */
+int odp_packet_inflag_sctp(odp_packet_t pkt);
+
+/**
+ * Check for ICMP
+ *
+ * @param pkt Packet handle
+ * @return 1 if packet contains an ICMP header, 0 otherwise
+ */
+int odp_packet_inflag_icmp(odp_packet_t pkt);
+
+/**
+ * Request L4 checksum calculation
+ *
+ * @param pkt Packet handle
+ */
+void odp_packet_outflag_l4_chksum(odp_packet_t pkt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/Makefile b/platform/linux-generic/Makefile
index f665683..b640928 100644
--- a/platform/linux-generic/Makefile
+++ b/platform/linux-generic/Makefile
@@ -54,6 +54,7 @@  OBJS    += $(OBJ_DIR)/odp_coremask.o
 OBJS    += $(OBJ_DIR)/odp_init.o
 OBJS    += $(OBJ_DIR)/odp_linux.o
 OBJS    += $(OBJ_DIR)/odp_packet.o
+OBJS    += $(OBJ_DIR)/odp_packet_flags.o
 OBJS    += $(OBJ_DIR)/odp_packet_io.o
 OBJS    += $(OBJ_DIR)/odp_packet_socket.o
 OBJS    += $(OBJ_DIR)/odp_queue.o
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
index afef976..f0dda95 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -25,59 +25,98 @@  extern "C" {
 #include <odp_packet.h>
 #include <odp_packet_io.h>
 
-typedef struct {
-	uint32_t l2:1;
-	uint32_t l3:1;
-	uint32_t l4:1;
-
-	uint32_t macsec:1;
-	uint32_t vlan:1;
-	uint32_t vlan_double:1;
-	uint32_t ipv4:1;
-	uint32_t ipv6:1;
-	uint32_t ip_frag:1;
-	uint32_t udp:1;
-	uint32_t tcp:1;
-	uint32_t icmp:1;
-} proto_flags_t;
+/**
+ * Packet input & protocol flags
+ */
+typedef union {
+	/* All input flags */
+	uint32_t all;
 
-typedef struct {
-	uint32_t frame_len:1;
-	uint32_t l2_chksum:1;
-	uint32_t ip_err:1;
-	uint32_t tcp_err:1;
-	uint32_t udp_err:1;
+	/* Bitfield flags for each protocol */
+	uint32_t l2:1;        /**< known L2 protocol present */
+	uint32_t l3:1;        /**< known L3 protocol present */
+	uint32_t l4:1;        /**< known L4 protocol present */
+
+	uint32_t eth:1;       /**< Ethernet */
+	uint32_t jumbo:1;     /**< Jumbo frame */
+	uint32_t vlan:1;      /**< VLAN hdr found */
+	uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */
+
+	uint32_t arp:1;       /**< ARP */
+
+	uint32_t ipv4:1;      /**< IPv4 */
+	uint32_t ipv6:1;      /**< IPv6 */
+	uint32_t ipfrag:1;    /**< IP fragment */
+	uint32_t ipopt:1;     /**< IP optional headers */
+	uint32_t ipsec;       /**< IPSec decryption may be needed */
+
+	uint32_t udp:1;       /**< UDP */
+	uint32_t tcp:1;       /**< TCP */
+	uint32_t sctp:1;      /**< SCTP */
+	uint32_t icmp:1;      /**< ICMP */
+} input_flags_t;
+
+ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t), INPUT_FLAGS_SIZE_ERROR);
+
+/**
+ * Packet error flags
+ */
+typedef union {
+	/* All error flags */
+	uint32_t all;
+
+	/* Bitfield flags for each detected error */
+	uint32_t frame_len:1; /**< Frame length error */
+	uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD */
+	uint32_t ip_err:1;    /**< IP error,  checks TBD */
+	uint32_t tcp_err:1;   /**< TCP error, checks TBD */
+	uint32_t udp_err:1;   /**< UDP error, checks TBD */
 } error_flags_t;
 
-typedef struct {
-	uint32_t calc_l4_chksum:1;
+ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t), ERROR_FLAGS_SIZE_ERROR);
+
+/**
+ * Packet output flags
+ */
+typedef union {
+	/* All output flags */
+	uint32_t all;
+
+	/* Bitfield flags for each output option */
+	uint32_t l4_chksum:1; /**< Request L4 checksum calculation */
 } output_flags_t;
 
+ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), OUTPUT_FLAGS_SIZE_ERROR);
+
 /**
  * Internal Packet header
  */
-typedef struct odp_packet_hdr_t {
+typedef struct {
 	/* common buffer header */
 	odp_buffer_hdr_t buf_hdr;
 
-	proto_flags_t  proto_flags;
+	input_flags_t  input_flags;
 	error_flags_t  error_flags;
 	output_flags_t output_flags;
 
-	uint32_t l2_offset;
-	uint32_t l3_offset;
-	uint32_t l4_offset;
+	uint32_t frame_offset; /**< offset to start of frame, even on error */
+	uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */
+	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 frame_len;
 
 	odp_pktio_t input;
 
+	uint32_t pad;
 	uint8_t payload[];
 
 } odp_packet_hdr_t;
 
 ODP_ASSERT(sizeof(odp_packet_hdr_t) == ODP_OFFSETOF(odp_packet_hdr_t, payload),
 	   ODP_PACKET_HDR_T__SIZE_ERR);
+ODP_ASSERT(sizeof(odp_packet_hdr_t) % sizeof(uint64_t) == 0,
+	   ODP_PACKET_HDR_T__SIZE_ERR2);
 
 /**
  * Return the packet header
diff --git a/platform/linux-generic/source/odp_packet.c b/platform/linux-generic/source/odp_packet.c
index 6b06f76..6ee2c5b 100644
--- a/platform/linux-generic/source/odp_packet.c
+++ b/platform/linux-generic/source/odp_packet.c
@@ -124,7 +124,7 @@  void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset)
 	if (odp_unlikely(len < ODP_ETH_LEN_MIN))
 		pkt_hdr->error_flags.frame_len = 1;
 
-	pkt_hdr->proto_flags.l2 = 1;
+	pkt_hdr->input_flags.l2 = 1;
 	pkt_hdr->l2_offset = l2_offset;
 	eth = (odp_ethhdr_t *)odp_packet_l2(pkt);
 
@@ -132,25 +132,25 @@  void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset)
 	vlan = (odp_vlanhdr_t *)&eth->type;
 
 	if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
-		pkt_hdr->proto_flags.vlan_double = 1;
+		pkt_hdr->input_flags.vlan_qinq = 1;
 		ethtype = odp_be_to_cpu_16(vlan->tpid);
 		offset += sizeof(odp_vlanhdr_t);
 		vlan = &vlan[1];
 	}
 
 	if (ethtype == ODP_ETHTYPE_VLAN) {
-		pkt_hdr->proto_flags.vlan = 1;
+		pkt_hdr->input_flags.vlan = 1;
 		ethtype = odp_be_to_cpu_16(vlan->tpid);
 		offset += sizeof(odp_vlanhdr_t);
 	}
 
-	pkt_hdr->proto_flags.l3 = 1;
+	pkt_hdr->input_flags.l3 = 1;
 	pkt_hdr->l3_offset = l2_offset + ODP_ETHHDR_LEN + offset;
 
 	if (ethtype == ODP_ETHTYPE_IPV4) {
 		uint8_t ihl;
 
-		pkt_hdr->proto_flags.ipv4 = 1;
+		pkt_hdr->input_flags.ipv4 = 1;
 		ip = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
 
 		ihl = ODP_IPV4HDR_IHL(ip->ver_ihl);
@@ -159,19 +159,19 @@  void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset)
 			return;
 		}
 
-		pkt_hdr->proto_flags.l4 = 1;
+		pkt_hdr->input_flags.l4 = 1;
 		pkt_hdr->l4_offset = pkt_hdr->l3_offset +
 				     sizeof(uint32_t) * ihl;
 
 		switch (ip->proto) {
 		case ODP_IPPROTO_UDP:
-			pkt_hdr->proto_flags.udp = 1;
+			pkt_hdr->input_flags.udp = 1;
 			break;
 		case ODP_IPPROTO_TCP:
-			pkt_hdr->proto_flags.tcp = 1;
+			pkt_hdr->input_flags.tcp = 1;
 			break;
 		case ODP_IPPROTO_ICMP:
-			pkt_hdr->proto_flags.icmp = 1;
+			pkt_hdr->input_flags.icmp = 1;
 			break;
 		}
 	}
diff --git a/platform/linux-generic/source/odp_packet_flags.c b/platform/linux-generic/source/odp_packet_flags.c
new file mode 100644
index 0000000..0fd0aa9
--- /dev/null
+++ b/platform/linux-generic/source/odp_packet_flags.c
@@ -0,0 +1,116 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+ #include <odp_packet_flags.h>
+ #include <odp_packet_internal.h>
+
+
+int odp_packet_error(odp_packet_t pkt)
+{
+	return (odp_packet_hdr(pkt)->error_flags.all != 0);
+}
+
+/* Get Error Flags */
+
+int odp_packet_errflag_frame_len(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->error_flags.frame_len;
+}
+
+/* Get Input Flags */
+
+int odp_packet_inflag_l2(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.l2;
+}
+
+int odp_packet_inflag_l3(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.l3;
+}
+
+int odp_packet_inflag_l4(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.l4;
+}
+
+int odp_packet_inflag_eth(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.eth;
+}
+
+int odp_packet_inflag_jumbo(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.jumbo;
+}
+
+int odp_packet_inflag_vlan(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.vlan;
+}
+
+int odp_packet_inflag_vlan_qinq(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.vlan_qinq;
+}
+
+int odp_packet_inflag_arp(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.arp;
+}
+
+int odp_packet_inflag_ipv4(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.ipv4;
+}
+
+int odp_packet_inflag_ipv6(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.ipv6;
+}
+
+int odp_packet_inflag_ipfrag(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.ipfrag;
+}
+
+int odp_packet_inflag_ipopt(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.ipopt;
+}
+
+int odp_packet_inflag_ipsec(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.ipsec;
+}
+
+int odp_packet_inflag_udp(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.udp;
+}
+
+int odp_packet_inflag_tcp(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.tcp;
+}
+
+int odp_packet_inflag_sctp(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.sctp;
+}
+
+int odp_packet_inflag_icmp(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input_flags.icmp;
+}
+
+/* Set Output Flags */
+
+void odp_packet_outflag_l4_chksum(odp_packet_t pkt)
+{
+	odp_packet_hdr(pkt)->output_flags.l4_chksum = 1;
+}
+