Replace old lazy parsing code with a new packet parsing implementation
which follows the latest API (parsing level is selected using
odp_pktio_config()).

Signed-off-by: Matias Elo <[email protected]>
Reviewed-and-tested-by: Bill Fischofer <[email protected]>
---
 .../include/odp/api/plat/packet_types.h            |   1 -
 .../linux-generic/include/odp_packet_internal.h    |  39 +--
 platform/linux-generic/odp_classification.c        |   7 +-
 platform/linux-generic/odp_packet.c                | 382 ++++++++-------------
 platform/linux-generic/odp_packet_flags.c          | 111 +++---
 platform/linux-generic/odp_packet_io.c             |   2 +
 platform/linux-generic/pktio/dpdk.c                |   3 +-
 platform/linux-generic/pktio/loop.c                |   3 +-
 platform/linux-generic/pktio/netmap.c              |   3 +-
 platform/linux-generic/pktio/pcap.c                |   3 +-
 platform/linux-generic/pktio/socket.c              |   3 +-
 platform/linux-generic/pktio/socket_mmap.c         |   3 +-
 platform/linux-generic/pktio/tap.c                 |   3 +-
 13 files changed, 217 insertions(+), 346 deletions(-)

diff --git a/platform/linux-generic/include/odp/api/plat/packet_types.h 
b/platform/linux-generic/include/odp/api/plat/packet_types.h
index b8f665d..f4e8501 100644
--- a/platform/linux-generic/include/odp/api/plat/packet_types.h
+++ b/platform/linux-generic/include/odp/api/plat/packet_types.h
@@ -96,7 +96,6 @@ typedef union {
        uint64_t all;
 
        struct {
-               uint64_t parsed_l2:1; /**< L2 parsed */
                uint64_t dst_queue:1; /**< Dst queue present */
 
                uint64_t flow_hash:1; /**< Flow hash present */
diff --git a/platform/linux-generic/include/odp_packet_internal.h 
b/platform/linux-generic/include/odp_packet_internal.h
index 0a9f177..d0db700 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -80,18 +80,6 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t),
                  "OUTPUT_FLAGS_SIZE_ERROR");
 
 /**
- * Protocol stack layers
- */
-typedef enum {
-       LAYER_NONE = 0,
-       LAYER_L1,
-       LAYER_L2,
-       LAYER_L3,
-       LAYER_L4,
-       LAYER_ALL
-} layer_t;
-
-/**
  * Packet parser metadata
  */
 typedef struct {
@@ -102,14 +90,6 @@ typedef struct {
        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 l3_len;    /**< Layer 3 length */
-       uint32_t l4_len;    /**< Layer 4 length */
-
-       uint16_t ethtype;       /**< EtherType */
-       uint8_t  ip_proto;      /**< IP protocol */
-       uint8_t  parsed_layers; /**< Highest parsed protocol stack layer */
-
 } packet_parser_t;
 
 /**
@@ -203,16 +183,6 @@ static inline void packet_set_len(odp_packet_hdr_t 
*pkt_hdr, uint32_t len)
        pkt_hdr->frame_len = len;
 }
 
-static inline int packet_parse_l2_not_done(packet_parser_t *prs)
-{
-       return !prs->input_flags.parsed_l2;
-}
-
-static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr)
-{
-       return pkt_hdr->p.parsed_layers != LAYER_ALL;
-}
-
 /* Forward declarations */
 int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt);
 
@@ -220,11 +190,9 @@ int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, 
odp_packet_t dstpkt);
 int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len,
                       odp_packet_t pkt[], int max_num);
 
-/* Fill in parser metadata for L2 */
-void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len);
-
 /* Perform packet parse up to a given protocol layer */
-int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer);
+int packet_parse_layer(odp_packet_hdr_t *pkt_hdr,
+                      odp_pktio_parser_layer_t layer);
 
 /* Reset parser metadata for a new parse */
 void packet_parse_reset(odp_packet_hdr_t *pkt_hdr);
@@ -264,7 +232,8 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, 
odp_time_t *ts)
 }
 
 int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr,
-                       uint32_t pkt_len, uint32_t seg_len, layer_t layer);
+                       uint32_t pkt_len, uint32_t seg_len,
+                       odp_pktio_parser_layer_t layer);
 
 int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr);
 
diff --git a/platform/linux-generic/odp_classification.c 
b/platform/linux-generic/odp_classification.c
index 5d96b00..7ebc47d 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -790,10 +790,6 @@ static inline cos_t *cls_select_cos(pktio_entry_t *entry,
        cls = &entry->s.cls;
        default_cos = cls->default_cos;
 
-       /* Check for lazy parse needed */
-       if (packet_parse_not_complete(pkt_hdr))
-               packet_parse_layer(pkt_hdr, LAYER_ALL);
-
        /* Return error cos for error packet */
        if (pkt_hdr->p.error_flags.all)
                return cls->error_cos;
@@ -838,7 +834,8 @@ int cls_classify_packet(pktio_entry_t *entry, const uint8_t 
*base,
        packet_parse_reset(pkt_hdr);
        packet_set_len(pkt_hdr, pkt_len);
 
-       packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len, LAYER_ALL);
+       packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len,
+                           ODP_PKTIO_PARSER_LAYER_ALL);
        cos = cls_select_cos(entry, base, pkt_hdr);
 
        if (cos == NULL)
diff --git a/platform/linux-generic/odp_packet.c 
b/platform/linux-generic/odp_packet.c
index a75c191..0b70c5c 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -220,16 +220,9 @@ static inline void *packet_map(odp_packet_hdr_t *pkt_hdr,
        return addr;
 }
 
-static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr)
-{
-       pkt_hdr->p.input_flags.parsed_l2  = 1;
-       pkt_hdr->p.parsed_layers = LAYER_ALL;
-}
-
 void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
 {
        /* Reset parser metadata before new parse */
-       pkt_hdr->p.parsed_layers    = LAYER_NONE;
        pkt_hdr->p.error_flags.all  = 0;
        pkt_hdr->p.input_flags.all  = 0;
        pkt_hdr->p.output_flags.all = 0;
@@ -241,8 +234,7 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
 /**
  * Initialize packet
  */
-static inline void packet_init(odp_packet_hdr_t *pkt_hdr, uint32_t len,
-                              int parse)
+static inline void packet_init(odp_packet_hdr_t *pkt_hdr, uint32_t len)
 {
        uint32_t seg_len;
        int num = pkt_hdr->buf_hdr.segcount;
@@ -257,7 +249,6 @@ static inline void packet_init(odp_packet_hdr_t *pkt_hdr, 
uint32_t len,
                pkt_hdr->buf_hdr.seg[num - 1].len = seg_len;
        }
 
-       pkt_hdr->p.parsed_layers    = LAYER_NONE;
        pkt_hdr->p.input_flags.all  = 0;
        pkt_hdr->p.output_flags.all = 0;
        pkt_hdr->p.error_flags.all  = 0;
@@ -266,10 +257,6 @@ static inline void packet_init(odp_packet_hdr_t *pkt_hdr, 
uint32_t len,
        pkt_hdr->p.l3_offset = ODP_PACKET_OFFSET_INVALID;
        pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID;
 
-       /* Disable lazy parsing on user allocated packets */
-       if (!parse)
-               packet_parse_disable(pkt_hdr);
-
        /*
        * Packet headroom is set from the pool's headroom
        * Packet tailroom is rounded up to fill the last
@@ -485,7 +472,7 @@ static inline odp_packet_hdr_t 
*free_segments(odp_packet_hdr_t *pkt_hdr,
 }
 
 static inline int packet_alloc(pool_t *pool, uint32_t len, int max_pkt,
-                              int num_seg, odp_packet_t *pkt, int parse)
+                              int num_seg, odp_packet_t *pkt)
 {
        int num_buf, i;
        int num     = max_pkt;
@@ -518,7 +505,7 @@ static inline int packet_alloc(pool_t *pool, uint32_t len, 
int max_pkt,
                pkt[i] = packet_handle(hdr);
                init_segments(&pkt_hdr[i * num_seg], num_seg);
 
-               packet_init(hdr, len, parse);
+               packet_init(hdr, len);
        }
 
        return num;
@@ -531,7 +518,7 @@ int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len,
        int num, num_seg;
 
        num_seg = num_segments(len);
-       num     = packet_alloc(pool, len, max_num, num_seg, pkt, 1);
+       num     = packet_alloc(pool, len, max_num, num_seg, pkt);
 
        return num;
 }
@@ -551,7 +538,7 @@ odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t 
len)
                return ODP_PACKET_INVALID;
 
        num_seg = num_segments(len);
-       num     = packet_alloc(pool, len, 1, num_seg, &pkt, 0);
+       num     = packet_alloc(pool, len, 1, num_seg, &pkt);
 
        if (odp_unlikely(num == 0))
                return ODP_PACKET_INVALID;
@@ -574,7 +561,7 @@ int odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t 
len,
                return -1;
 
        num_seg = num_segments(len);
-       num     = packet_alloc(pool, len, max_num, num_seg, pkt, 0);
+       num     = packet_alloc(pool, len, max_num, num_seg, pkt);
 
        return num;
 }
@@ -630,7 +617,7 @@ int odp_packet_reset(odp_packet_t pkt, uint32_t len)
        if (len > pool->headroom + pool->data_size + pool->tailroom)
                return -1;
 
-       packet_init(pkt_hdr, len, 0);
+       packet_init(pkt_hdr, len);
 
        return 0;
 }
@@ -1241,8 +1228,6 @@ void *odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len)
 {
        odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt);
 
-       if (pkt_hdr->p.parsed_layers < LAYER_L3)
-               packet_parse_layer(pkt_hdr, LAYER_L3);
        return packet_map(pkt_hdr, pkt_hdr->p.l3_offset, len, NULL);
 }
 
@@ -1250,8 +1235,6 @@ uint32_t odp_packet_l3_offset(odp_packet_t pkt)
 {
        odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt);
 
-       if (pkt_hdr->p.parsed_layers < LAYER_L3)
-               packet_parse_layer(pkt_hdr, LAYER_L3);
        return pkt_hdr->p.l3_offset;
 }
 
@@ -1262,8 +1245,6 @@ int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t 
offset)
        if (offset >= pkt_hdr->frame_len)
                return -1;
 
-       if (pkt_hdr->p.parsed_layers < LAYER_L3)
-               packet_parse_layer(pkt_hdr, LAYER_L3);
        pkt_hdr->p.l3_offset = offset;
        return 0;
 }
@@ -1272,8 +1253,6 @@ void *odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len)
 {
        odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt);
 
-       if (pkt_hdr->p.parsed_layers < LAYER_L4)
-               packet_parse_layer(pkt_hdr, LAYER_L4);
        return packet_map(pkt_hdr, pkt_hdr->p.l4_offset, len, NULL);
 }
 
@@ -1281,8 +1260,6 @@ uint32_t odp_packet_l4_offset(odp_packet_t pkt)
 {
        odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt);
 
-       if (pkt_hdr->p.parsed_layers < LAYER_L4)
-               packet_parse_layer(pkt_hdr, LAYER_L4);
        return pkt_hdr->p.l4_offset;
 }
 
@@ -1293,8 +1270,6 @@ int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t 
offset)
        if (offset >= pkt_hdr->frame_len)
                return -1;
 
-       if (pkt_hdr->p.parsed_layers < LAYER_L4)
-               packet_parse_layer(pkt_hdr, LAYER_L4);
        pkt_hdr->p.l4_offset = offset;
        return 0;
 }
@@ -1773,12 +1748,11 @@ static inline uint8_t parse_ipv4(packet_parser_t *prs, 
const uint8_t **parseptr,
        uint8_t ihl = _ODP_IPV4HDR_IHL(ipv4->ver_ihl);
        uint16_t frag_offset;
        uint32_t dstaddr = odp_be_to_cpu_32(ipv4->dst_addr);
-
-       prs->l3_len = odp_be_to_cpu_16(ipv4->tot_len);
+       uint32_t l3_len = odp_be_to_cpu_16(ipv4->tot_len);
 
        if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN) ||
            odp_unlikely(ver != 4) ||
-           (prs->l3_len > frame_len - *offset)) {
+           (l3_len > frame_len - *offset)) {
                prs->error_flags.ip_err = 1;
                return 0;
        }
@@ -1815,13 +1789,12 @@ static inline uint8_t parse_ipv6(packet_parser_t *prs, 
const uint8_t **parseptr,
        const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr;
        const _odp_ipv6hdr_ext_t *ipv6ext;
        uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr.u8[0]);
-
-       prs->l3_len = odp_be_to_cpu_16(ipv6->payload_len) +
-                               _ODP_IPV6HDR_LEN;
+       uint32_t l3_len = odp_be_to_cpu_16(ipv6->payload_len) +
+                       _ODP_IPV6HDR_LEN;
 
        /* Basic sanity checks on IPv6 header */
        if ((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 ||
-           prs->l3_len > frame_len - *offset) {
+           l3_len > frame_len - *offset) {
                prs->error_flags.ip_err = 1;
                return 0;
        }
@@ -1882,9 +1855,6 @@ static inline void parse_tcp(packet_parser_t *prs,
        else if ((uint32_t)tcp->hl * 4 > sizeof(_odp_tcphdr_t))
                prs->input_flags.tcpopt = 1;
 
-       prs->l4_len = prs->l3_len +
-               prs->l3_offset - prs->l4_offset;
-
        if (offset)
                *offset   += (uint32_t)tcp->hl * 4;
        *parseptr += (uint32_t)tcp->hl * 4;
@@ -1899,13 +1869,8 @@ static inline void parse_udp(packet_parser_t *prs,
        const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr;
        uint32_t udplen = odp_be_to_cpu_16(udp->length);
 
-       if (udplen < sizeof(_odp_udphdr_t) ||
-           udplen > (prs->l3_len +
-                     prs->l4_offset - prs->l3_offset)) {
+       if (odp_unlikely(udplen < sizeof(_odp_udphdr_t)))
                prs->error_flags.udp_err = 1;
-       }
-
-       prs->l4_len = udplen;
 
        if (offset)
                *offset   += sizeof(_odp_udphdr_t);
@@ -1913,218 +1878,170 @@ static inline void parse_udp(packet_parser_t *prs,
 }
 
 /**
- * Initialize L2 related parser flags and metadata
- */
-void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len)
-{
-       /* Packet alloc or reset have already init other offsets and flags */
-
-       /* We only support Ethernet for now */
-       prs->input_flags.eth = 1;
-
-       /* Detect jumbo frames */
-       if (frame_len > _ODP_ETH_LEN_MAX)
-               prs->input_flags.jumbo = 1;
-
-       /* Assume valid L2 header, no CRC/FCS check in SW */
-       prs->input_flags.l2 = 1;
-
-       prs->input_flags.parsed_l2 = 1;
-}
-
-/**
  * Parse common packet headers up to given layer
  *
  * The function expects at least PACKET_PARSE_SEG_LEN bytes of data to be
  * available from the ptr.
  */
 int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr,
-                       uint32_t frame_len, uint32_t seg_len, layer_t layer)
+                       uint32_t frame_len, uint32_t seg_len,
+                       odp_pktio_parser_layer_t layer)
 {
        uint32_t offset;
+       uint16_t ethtype;
        const uint8_t *parseptr;
+       uint8_t  ip_proto;
+       const _odp_ethhdr_t *eth;
+       uint16_t macaddr0, macaddr2, macaddr4;
+       const _odp_vlanhdr_t *vlan;
+
+       if (layer == ODP_PKTIO_PARSER_LAYER_NONE)
+               return 0;
+
+       /* We only support Ethernet for now */
+       prs->input_flags.eth = 1;
+       /* Assume valid L2 header, no CRC/FCS check in SW */
+       prs->input_flags.l2 = 1;
+       /* Detect jumbo frames */
+       if (frame_len > _ODP_ETH_LEN_MAX)
+               prs->input_flags.jumbo = 1;
+
+       offset = sizeof(_odp_ethhdr_t);
+       eth = (const _odp_ethhdr_t *)ptr;
+
+       /* Handle Ethernet broadcast/multicast addresses */
+       macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth));
+       prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100;
+
+       if (macaddr0 == 0xffff) {
+               macaddr2 =
+                       odp_be_to_cpu_16(*((const uint16_t *)
+                                          (const void *)eth + 1));
+               macaddr4 =
+                       odp_be_to_cpu_16(*((const uint16_t *)
+                                          (const void *)eth + 2));
+               prs->input_flags.eth_bcast =
+                       (macaddr2 == 0xffff) && (macaddr4 == 0xffff);
+       } else {
+               prs->input_flags.eth_bcast = 0;
+       }
 
-       switch (prs->parsed_layers) {
-       case LAYER_NONE:
-       /* Fall through */
+       /* Get Ethertype */
+       ethtype = odp_be_to_cpu_16(eth->type);
+       parseptr = (const uint8_t *)(eth + 1);
 
-       case LAYER_L2:
-       {
-               const _odp_ethhdr_t *eth;
-               uint16_t macaddr0, macaddr2, macaddr4;
-               const _odp_vlanhdr_t *vlan;
-
-               offset = sizeof(_odp_ethhdr_t);
-               if (packet_parse_l2_not_done(prs))
-                       packet_parse_l2(prs, frame_len);
-
-               eth = (const _odp_ethhdr_t *)ptr;
-
-               /* Handle Ethernet broadcast/multicast addresses */
-               macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)
-                                           (const void *)eth));
-               prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100;
-
-               if (macaddr0 == 0xffff) {
-                       macaddr2 =
-                               odp_be_to_cpu_16(*((const uint16_t *)
-                                                  (const void *)eth + 1));
-                       macaddr4 =
-                               odp_be_to_cpu_16(*((const uint16_t *)
-                                                  (const void *)eth + 2));
-                       prs->input_flags.eth_bcast =
-                               (macaddr2 == 0xffff) && (macaddr4 == 0xffff);
-               } else {
-                       prs->input_flags.eth_bcast = 0;
+       /* Check for SNAP vs. DIX */
+       if (ethtype < _ODP_ETH_LEN_MAX) {
+               prs->input_flags.snap = 1;
+               if (ethtype > frame_len - offset) {
+                       prs->error_flags.snap_len = 1;
+                       goto parse_exit;
                }
+               ethtype = odp_be_to_cpu_16(*((const uint16_t *)(uintptr_t)
+                                            (parseptr + 6)));
+               offset   += 8;
+               parseptr += 8;
+       }
 
-               /* Get Ethertype */
-               prs->ethtype = odp_be_to_cpu_16(eth->type);
-               parseptr = (const uint8_t *)(eth + 1);
-
-               /* Check for SNAP vs. DIX */
-               if (prs->ethtype < _ODP_ETH_LEN_MAX) {
-                       prs->input_flags.snap = 1;
-                       if (prs->ethtype > frame_len - offset) {
-                               prs->error_flags.snap_len = 1;
-                               goto parse_exit;
-                       }
-                       prs->ethtype = odp_be_to_cpu_16(*((const uint16_t *)
-                                                       (uintptr_t)
-                                                       (parseptr + 6)));
-                       offset   += 8;
-                       parseptr += 8;
-               }
+       /* Parse the VLAN header(s), if present */
+       if (ethtype == _ODP_ETHTYPE_VLAN_OUTER) {
+               prs->input_flags.vlan_qinq = 1;
+               prs->input_flags.vlan = 1;
 
-               /* Parse the VLAN header(s), if present */
-               if (prs->ethtype == _ODP_ETHTYPE_VLAN_OUTER) {
-                       prs->input_flags.vlan_qinq = 1;
-                       prs->input_flags.vlan = 1;
+               vlan = (const _odp_vlanhdr_t *)parseptr;
+               ethtype = odp_be_to_cpu_16(vlan->type);
+               offset += sizeof(_odp_vlanhdr_t);
+               parseptr += sizeof(_odp_vlanhdr_t);
+       }
 
-                       vlan = (const _odp_vlanhdr_t *)parseptr;
-                       prs->ethtype = odp_be_to_cpu_16(vlan->type);
-                       offset += sizeof(_odp_vlanhdr_t);
-                       parseptr += sizeof(_odp_vlanhdr_t);
-               }
+       if (ethtype == _ODP_ETHTYPE_VLAN) {
+               prs->input_flags.vlan = 1;
+               vlan = (const _odp_vlanhdr_t *)parseptr;
+               ethtype = odp_be_to_cpu_16(vlan->type);
+               offset += sizeof(_odp_vlanhdr_t);
+               parseptr += sizeof(_odp_vlanhdr_t);
+       }
 
-               if (prs->ethtype == _ODP_ETHTYPE_VLAN) {
-                       prs->input_flags.vlan = 1;
-                       vlan = (const _odp_vlanhdr_t *)parseptr;
-                       prs->ethtype = odp_be_to_cpu_16(vlan->type);
-                       offset += sizeof(_odp_vlanhdr_t);
-                       parseptr += sizeof(_odp_vlanhdr_t);
-               }
+       if (layer == ODP_PKTIO_PARSER_LAYER_L2)
+               return prs->error_flags.all != 0;
 
-               prs->l3_offset = offset;
-               prs->parsed_layers = LAYER_L2;
-               if (layer == LAYER_L2)
-                       return prs->error_flags.all != 0;
-       }
-       /* Fall through */
+       /* Set l3_offset+flag only for known ethtypes */
+       prs->l3_offset = offset;
+       prs->input_flags.l3 = 1;
 
-       case LAYER_L3:
-       {
-               offset = prs->l3_offset;
-               parseptr = (const uint8_t *)(ptr + offset);
-               /* Set l3_offset+flag only for known ethtypes */
-               prs->input_flags.l3 = 1;
-
-               /* Parse Layer 3 headers */
-               switch (prs->ethtype) {
-               case _ODP_ETHTYPE_IPV4:
-                       prs->input_flags.ipv4 = 1;
-                       prs->ip_proto = parse_ipv4(prs, &parseptr, &offset,
-                                                  frame_len);
-                       break;
-
-               case _ODP_ETHTYPE_IPV6:
-                       prs->input_flags.ipv6 = 1;
-                       prs->ip_proto = parse_ipv6(prs, &parseptr, &offset,
-                                                  frame_len, seg_len);
-                       break;
-
-               case _ODP_ETHTYPE_ARP:
-                       prs->input_flags.arp = 1;
-                       prs->ip_proto = 255;  /* Reserved invalid by IANA */
-                       break;
-
-               default:
-                       prs->input_flags.l3 = 0;
-                       prs->l3_offset = ODP_PACKET_OFFSET_INVALID;
-                       prs->ip_proto = 255;  /* Reserved invalid by IANA */
-               }
+       /* Parse Layer 3 headers */
+       switch (ethtype) {
+       case _ODP_ETHTYPE_IPV4:
+               prs->input_flags.ipv4 = 1;
+               ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len);
+               break;
+
+       case _ODP_ETHTYPE_IPV6:
+               prs->input_flags.ipv6 = 1;
+               ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len,
+                                     seg_len);
+               break;
+
+       case _ODP_ETHTYPE_ARP:
+               prs->input_flags.arp = 1;
+               ip_proto = 255;  /* Reserved invalid by IANA */
+               break;
 
-               /* Set l4_offset+flag only for known ip_proto */
-               prs->l4_offset = offset;
-               prs->parsed_layers = LAYER_L3;
-               if (layer == LAYER_L3)
-                       return prs->error_flags.all != 0;
+       default:
+               prs->input_flags.l3 = 0;
+               prs->l3_offset = ODP_PACKET_OFFSET_INVALID;
+               ip_proto = 255;  /* Reserved invalid by IANA */
        }
+
+       if (layer == ODP_PKTIO_PARSER_LAYER_L3)
+               return prs->error_flags.all != 0;
+
+       /* Set l4_offset+flag only for known ip_proto */
+       prs->l4_offset = offset;
+       prs->input_flags.l4 = 1;
+
+       /* Parse Layer 4 headers */
+       switch (ip_proto) {
+       case _ODP_IPPROTO_ICMPv4:
        /* Fall through */
 
-       case LAYER_L4:
-       {
-               offset = prs->l4_offset;
-               parseptr = (const uint8_t *)(ptr + offset);
-               prs->input_flags.l4 = 1;
-
-               /* Parse Layer 4 headers */
-               switch (prs->ip_proto) {
-               case _ODP_IPPROTO_ICMPv4:
-               /* Fall through */
-
-               case _ODP_IPPROTO_ICMPv6:
-                       prs->input_flags.icmp = 1;
-                       break;
-
-               case _ODP_IPPROTO_TCP:
-                       if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len))
-                               return -1;
-                       prs->input_flags.tcp = 1;
-                       parse_tcp(prs, &parseptr, NULL);
-                       break;
-
-               case _ODP_IPPROTO_UDP:
-                       if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len))
-                               return -1;
-                       prs->input_flags.udp = 1;
-                       parse_udp(prs, &parseptr, NULL);
-                       break;
-
-               case _ODP_IPPROTO_AH:
-                       prs->input_flags.ipsec = 1;
-                       prs->input_flags.ipsec_ah = 1;
-                       break;
-
-               case _ODP_IPPROTO_ESP:
-                       prs->input_flags.ipsec = 1;
-                       prs->input_flags.ipsec_esp = 1;
-                       break;
-
-               case _ODP_IPPROTO_SCTP:
-                       prs->input_flags.sctp = 1;
-                       break;
-
-               default:
-                       prs->input_flags.l4 = 0;
-                       prs->l4_offset = ODP_PACKET_OFFSET_INVALID;
-                       break;
-               }
+       case _ODP_IPPROTO_ICMPv6:
+               prs->input_flags.icmp = 1;
+               break;
 
-               prs->parsed_layers = LAYER_L4;
+       case _ODP_IPPROTO_TCP:
+               if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len))
+                       return -1;
+               prs->input_flags.tcp = 1;
+               parse_tcp(prs, &parseptr, NULL);
                break;
-       }
 
-       case LAYER_ALL:
+       case _ODP_IPPROTO_UDP:
+               if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len))
+                       return -1;
+               prs->input_flags.udp = 1;
+               parse_udp(prs, &parseptr, NULL);
                break;
 
-       default:
-               ODP_ERR("Invalid parse layer: %d\n", (int)layer);
-               return -1;
-       }
+       case _ODP_IPPROTO_AH:
+               prs->input_flags.ipsec = 1;
+               prs->input_flags.ipsec_ah = 1;
+               break;
+
+       case _ODP_IPPROTO_ESP:
+               prs->input_flags.ipsec = 1;
+               prs->input_flags.ipsec_esp = 1;
+               break;
 
-       prs->parsed_layers = LAYER_ALL;
+       case _ODP_IPPROTO_SCTP:
+               prs->input_flags.sctp = 1;
+               break;
 
+       default:
+               prs->input_flags.l4 = 0;
+               prs->l4_offset = ODP_PACKET_OFFSET_INVALID;
+               break;
+       }
 parse_exit:
        return prs->error_flags.all != 0;
 }
@@ -2132,7 +2049,8 @@ parse_exit:
 /**
  * Simple packet parser
  */
-int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer)
+int packet_parse_layer(odp_packet_hdr_t *pkt_hdr,
+                      odp_pktio_parser_layer_t layer)
 {
        uint32_t seg_len = packet_first_seg_len(pkt_hdr);
        void *base = packet_data(pkt_hdr);
diff --git a/platform/linux-generic/odp_packet_flags.c 
b/platform/linux-generic/odp_packet_flags.c
index ea9a227..bb993e8 100644
--- a/platform/linux-generic/odp_packet_flags.c
+++ b/platform/linux-generic/odp_packet_flags.c
@@ -8,17 +8,13 @@
 #include <odp/api/packet_flags.h>
 #include <odp_packet_internal.h>
 
-#define retflag(pkt, x, layer) do {                      \
+#define retflag(pkt, x) do {                             \
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); \
-       if (pkt_hdr->p.parsed_layers < layer)            \
-               packet_parse_layer(pkt_hdr, layer);      \
        return pkt_hdr->p.x;                             \
        } while (0)
 
-#define setflag(pkt, x, v, layer) do {                   \
+#define setflag(pkt, x, v) do {                          \
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); \
-       if (pkt_hdr->p.parsed_layers < layer)            \
-               packet_parse_layer(pkt_hdr, layer);      \
        pkt_hdr->p.x = v & 1;                            \
        } while (0)
 
@@ -26,9 +22,7 @@ int odp_packet_has_error(odp_packet_t pkt)
 {
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
 
-       if (packet_parse_not_complete(pkt_hdr))
-               packet_parse_layer(pkt_hdr, LAYER_ALL);
-       return odp_packet_hdr(pkt)->p.error_flags.all != 0;
+       return pkt_hdr->p.error_flags.all != 0;
 }
 
 /* Get Input Flags */
@@ -45,126 +39,117 @@ int odp_packet_has_l2_error(odp_packet_t pkt)
 
 int odp_packet_has_l3(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.l3, LAYER_L3);
+       retflag(pkt, input_flags.l3);
 }
 
 int odp_packet_has_l3_error(odp_packet_t pkt)
 {
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
 
-       if (pkt_hdr->p.parsed_layers < LAYER_L3)
-               packet_parse_layer(pkt_hdr, LAYER_L3);
-
        return pkt_hdr->p.error_flags.ip_err;
 }
 
 int odp_packet_has_l4(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.l4, LAYER_L4);
+       retflag(pkt, input_flags.l4);
 }
 
 int odp_packet_has_l4_error(odp_packet_t pkt)
 {
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
 
-       if (pkt_hdr->p.parsed_layers < LAYER_L4)
-               packet_parse_layer(pkt_hdr, LAYER_L4);
-
        return pkt_hdr->p.error_flags.tcp_err | pkt_hdr->p.error_flags.udp_err;
 }
 
 int odp_packet_has_eth_bcast(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.eth_bcast, LAYER_L2);
+       retflag(pkt, input_flags.eth_bcast);
 }
 
 int odp_packet_has_eth_mcast(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.eth_mcast, LAYER_L2);
+       retflag(pkt, input_flags.eth_mcast);
 }
 
 int odp_packet_has_vlan(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.vlan, LAYER_L2);
+       retflag(pkt, input_flags.vlan);
 }
 
 int odp_packet_has_vlan_qinq(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.vlan_qinq, LAYER_L2);
+       retflag(pkt, input_flags.vlan_qinq);
 }
 
 int odp_packet_has_arp(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.arp, LAYER_L3);
+       retflag(pkt, input_flags.arp);
 }
 
 int odp_packet_has_ipv4(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.ipv4, LAYER_L3);
+       retflag(pkt, input_flags.ipv4);
 }
 
 int odp_packet_has_ipv6(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.ipv6, LAYER_L3);
+       retflag(pkt, input_flags.ipv6);
 }
 
 int odp_packet_has_ip_bcast(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.ip_bcast, LAYER_L3);
+       retflag(pkt, input_flags.ip_bcast);
 }
 
 int odp_packet_has_ip_mcast(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.ip_mcast, LAYER_L3);
+       retflag(pkt, input_flags.ip_mcast);
 }
 
 int odp_packet_has_ipfrag(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.ipfrag, LAYER_L3);
+       retflag(pkt, input_flags.ipfrag);
 }
 
 int odp_packet_has_ipopt(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.ipopt, LAYER_L3);
+       retflag(pkt, input_flags.ipopt);
 }
 
 int odp_packet_has_ipsec(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.ipsec, LAYER_L4);
+       retflag(pkt, input_flags.ipsec);
 }
 
 int odp_packet_has_udp(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.udp, LAYER_L4);
+       retflag(pkt, input_flags.udp);
 }
 
 int odp_packet_has_tcp(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.tcp, LAYER_L4);
+       retflag(pkt, input_flags.tcp);
 }
 
 int odp_packet_has_sctp(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.sctp, LAYER_L4);
+       retflag(pkt, input_flags.sctp);
 }
 
 int odp_packet_has_icmp(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.icmp, LAYER_L4);
+       retflag(pkt, input_flags.icmp);
 }
 
 odp_packet_color_t odp_packet_color(odp_packet_t pkt)
 {
-       retflag(pkt, input_flags.color, LAYER_ALL);
+       retflag(pkt, input_flags.color);
 }
 
 void odp_packet_color_set(odp_packet_t pkt, odp_packet_color_t color)
 {
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
 
-       if (packet_parse_not_complete(pkt_hdr))
-               packet_parse_layer(pkt_hdr, LAYER_ALL);
-
        pkt_hdr->p.input_flags.color = color;
 }
 
@@ -172,29 +157,23 @@ odp_bool_t odp_packet_drop_eligible(odp_packet_t pkt)
 {
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
 
-       if (packet_parse_not_complete(pkt_hdr))
-               packet_parse_layer(pkt_hdr, LAYER_ALL);
-
        return !pkt_hdr->p.input_flags.nodrop;
 }
 
 void odp_packet_drop_eligible_set(odp_packet_t pkt, odp_bool_t drop)
 {
-       setflag(pkt, input_flags.nodrop, !drop, LAYER_ALL);
+       setflag(pkt, input_flags.nodrop, !drop);
 }
 
 int8_t odp_packet_shaper_len_adjust(odp_packet_t pkt)
 {
-       retflag(pkt, output_flags.shaper_len_adj, LAYER_ALL);
+       retflag(pkt, output_flags.shaper_len_adj);
 }
 
 void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj)
 {
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
 
-       if (packet_parse_not_complete(pkt_hdr))
-               packet_parse_layer(pkt_hdr, LAYER_ALL);
-
        pkt_hdr->p.output_flags.shaper_len_adj = adj;
 }
 
@@ -202,107 +181,107 @@ void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, 
int8_t adj)
 
 void odp_packet_has_l2_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.l2, val, LAYER_L2);
+       setflag(pkt, input_flags.l2, val);
 }
 
 void odp_packet_has_l3_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.l3, val, LAYER_L3);
+       setflag(pkt, input_flags.l3, val);
 }
 
 void odp_packet_has_l4_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.l4, val, LAYER_L4);
+       setflag(pkt, input_flags.l4, val);
 }
 
 void odp_packet_has_eth_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.eth, val, LAYER_L2);
+       setflag(pkt, input_flags.eth, val);
 }
 
 void odp_packet_has_eth_bcast_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.eth_bcast, val, LAYER_L2);
+       setflag(pkt, input_flags.eth_bcast, val);
 }
 
 void odp_packet_has_eth_mcast_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.eth_mcast, val, LAYER_L2);
+       setflag(pkt, input_flags.eth_mcast, val);
 }
 
 void odp_packet_has_jumbo_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.jumbo, val, LAYER_L2);
+       setflag(pkt, input_flags.jumbo, val);
 }
 
 void odp_packet_has_vlan_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.vlan, val, LAYER_L2);
+       setflag(pkt, input_flags.vlan, val);
 }
 
 void odp_packet_has_vlan_qinq_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.vlan_qinq, val, LAYER_L2);
+       setflag(pkt, input_flags.vlan_qinq, val);
 }
 
 void odp_packet_has_arp_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.arp, val, LAYER_L3);
+       setflag(pkt, input_flags.arp, val);
 }
 
 void odp_packet_has_ipv4_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.ipv4, val, LAYER_L3);
+       setflag(pkt, input_flags.ipv4, val);
 }
 
 void odp_packet_has_ipv6_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.ipv6, val, LAYER_L3);
+       setflag(pkt, input_flags.ipv6, val);
 }
 
 void odp_packet_has_ip_bcast_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.ip_bcast, val, LAYER_L3);
+       setflag(pkt, input_flags.ip_bcast, val);
 }
 
 void odp_packet_has_ip_mcast_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.ip_mcast, val, LAYER_L3);
+       setflag(pkt, input_flags.ip_mcast, val);
 }
 
 void odp_packet_has_ipfrag_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.ipfrag, val, LAYER_L3);
+       setflag(pkt, input_flags.ipfrag, val);
 }
 
 void odp_packet_has_ipopt_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.ipopt, val, LAYER_L3);
+       setflag(pkt, input_flags.ipopt, val);
 }
 
 void odp_packet_has_ipsec_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.ipsec, val, LAYER_L4);
+       setflag(pkt, input_flags.ipsec, val);
 }
 
 void odp_packet_has_udp_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.udp, val, LAYER_L4);
+       setflag(pkt, input_flags.udp, val);
 }
 
 void odp_packet_has_tcp_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.tcp, val, LAYER_L4);
+       setflag(pkt, input_flags.tcp, val);
 }
 
 void odp_packet_has_sctp_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.sctp, val, LAYER_L4);
+       setflag(pkt, input_flags.sctp, val);
 }
 
 void odp_packet_has_icmp_set(odp_packet_t pkt, int val)
 {
-       setflag(pkt, input_flags.icmp, val, LAYER_L4);
+       setflag(pkt, input_flags.icmp, val);
 }
 
 void odp_packet_has_flow_hash_clr(odp_packet_t pkt)
diff --git a/platform/linux-generic/odp_packet_io.c 
b/platform/linux-generic/odp_packet_io.c
index 5e783d8..d8cae15 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -206,6 +206,8 @@ static odp_pktio_t setup_pktio_entry(const char *name, 
odp_pool_t pool,
        memcpy(&pktio_entry->s.param, param, sizeof(odp_pktio_param_t));
        pktio_entry->s.handle = hdl;
 
+       odp_pktio_config_init(&pktio_entry->s.config);
+
        for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) {
                ret = pktio_if_ops[pktio_if]->open(hdl, pktio_entry, name,
                                                   pool);
diff --git a/platform/linux-generic/pktio/dpdk.c 
b/platform/linux-generic/pktio/dpdk.c
index 6ac89bd..c52cd09 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -653,7 +653,8 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry,
                if (pktio_cls_enabled(pktio_entry))
                        copy_packet_cls_metadata(&parsed_hdr, pkt_hdr);
                else
-                       packet_parse_l2(&pkt_hdr->p, pkt_len);
+                       packet_parse_layer(pkt_hdr,
+                                          pktio_entry->s.config.parser.layer);
 
                if (mbuf->ol_flags & PKT_RX_RSS_HASH)
                        odp_packet_flow_hash_set(pkt, mbuf->hash.rss);
diff --git a/platform/linux-generic/pktio/loop.c 
b/platform/linux-generic/pktio/loop.c
index 7096283..237a7e3 100644
--- a/platform/linux-generic/pktio/loop.c
+++ b/platform/linux-generic/pktio/loop.c
@@ -132,7 +132,8 @@ static int loopback_recv(pktio_entry_t *pktio_entry, int 
index ODP_UNUSED,
                if (pktio_cls_enabled(pktio_entry))
                        copy_packet_cls_metadata(&parsed_hdr, pkt_hdr);
                else
-                       packet_parse_l2(&pkt_hdr->p, pkt_len);
+                       packet_parse_layer(pkt_hdr,
+                                          pktio_entry->s.config.parser.layer);
 
                packet_set_ts(pkt_hdr, ts);
 
diff --git a/platform/linux-generic/pktio/netmap.c 
b/platform/linux-generic/pktio/netmap.c
index ae3db34..928bb00 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -663,7 +663,8 @@ static inline int netmap_pkt_to_odp(pktio_entry_t 
*pktio_entry,
                if (pktio_cls_enabled(pktio_entry))
                        copy_packet_cls_metadata(&parsed_hdr, pkt_hdr);
                else
-                       packet_parse_l2(&pkt_hdr->p, len);
+                       packet_parse_layer(pkt_hdr,
+                                          pktio_entry->s.config.parser.layer);
 
                packet_set_ts(pkt_hdr, ts);
        }
diff --git a/platform/linux-generic/pktio/pcap.c 
b/platform/linux-generic/pktio/pcap.c
index e54a56f..a467b64 100644
--- a/platform/linux-generic/pktio/pcap.c
+++ b/platform/linux-generic/pktio/pcap.c
@@ -252,7 +252,8 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, int 
index ODP_UNUSED,
                        break;
                }
 
-               packet_parse_l2(&pkt_hdr->p, pkt_len);
+               packet_parse_layer(pkt_hdr,
+                                  pktio_entry->s.config.parser.layer);
                pktio_entry->s.stats.in_octets += pkt_hdr->frame_len;
 
                packet_set_ts(pkt_hdr, ts);
diff --git a/platform/linux-generic/pktio/socket.c 
b/platform/linux-generic/pktio/socket.c
index 7d23968..89c6d46 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -749,7 +749,8 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int 
index ODP_UNUSED,
                        }
 
                        pkt_hdr = odp_packet_hdr(pkt);
-                       packet_parse_l2(&pkt_hdr->p, pkt_hdr->frame_len);
+                       packet_parse_layer(pkt_hdr,
+                                          pktio_entry->s.config.parser.layer);
                        packet_set_ts(pkt_hdr, ts);
                        pkt_hdr->input = pktio_entry->s.handle;
 
diff --git a/platform/linux-generic/pktio/socket_mmap.c 
b/platform/linux-generic/pktio/socket_mmap.c
index fdf8cca..2dba7b0 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -231,7 +231,8 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t 
*pktio_entry,
                if (pktio_cls_enabled(pktio_entry))
                        copy_packet_cls_metadata(&parsed_hdr, hdr);
                else
-                       packet_parse_l2(&hdr->p, pkt_len);
+                       packet_parse_layer(hdr,
+                                          pktio_entry->s.config.parser.layer);
 
                packet_set_ts(hdr, ts);
 
diff --git a/platform/linux-generic/pktio/tap.c 
b/platform/linux-generic/pktio/tap.c
index ac20456..650c12a 100644
--- a/platform/linux-generic/pktio/tap.c
+++ b/platform/linux-generic/pktio/tap.c
@@ -213,7 +213,8 @@ static odp_packet_t pack_odp_pkt(pktio_entry_t 
*pktio_entry, const void *data,
        if (pktio_cls_enabled(pktio_entry))
                copy_packet_cls_metadata(&parsed_hdr, pkt_hdr);
        else
-               packet_parse_l2(&pkt_hdr->p, len);
+               packet_parse_layer(pkt_hdr,
+                                  pktio_entry->s.config.parser.layer);
 
        packet_set_ts(pkt_hdr, ts);
        pkt_hdr->input = pktio_entry->s.handle;
-- 
2.7.4

Reply via email to