diff mbox

[1/2] initial odp dpdk

Message ID 1405103703-15084-1-git-send-email-venkatesh.vivekanandan@linaro.org
State New
Headers show

Commit Message

Venkatesh Vivekanandan July 11, 2014, 6:35 p.m. UTC
From: Vincent Hsu <vincent.hsu@linaro.org>

Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org>
---
 platform/linux-dpdk/Makefile                       | 158 ++++++
 platform/linux-dpdk/Makefile.inc                   |   7 +
 platform/linux-dpdk/include/api/odp_buffer.h       | 101 ++++
 platform/linux-dpdk/include/api/odp_buffer_pool.h  |  99 ++++
 platform/linux-dpdk/include/api/odp_packet.h       | 228 +++++++++
 platform/linux-dpdk/include/api/odp_pktio_types.h  |  45 ++
 platform/linux-dpdk/include/odp_buffer_internal.h  |  79 +++
 .../linux-dpdk/include/odp_buffer_pool_internal.h  |  90 ++++
 platform/linux-dpdk/include/odp_packet_dpdk.h      |  88 ++++
 platform/linux-dpdk/include/odp_packet_internal.h  | 140 +++++
 .../linux-dpdk/include/odp_packet_io_internal.h    |  52 ++
 platform/linux-dpdk/source/odp_buffer.c            | 102 ++++
 platform/linux-dpdk/source/odp_buffer_pool.c       | 156 ++++++
 platform/linux-dpdk/source/odp_init.c              | 113 +++++
 platform/linux-dpdk/source/odp_packet.c            | 374 ++++++++++++++
 platform/linux-dpdk/source/odp_packet_dpdk.c       | 177 +++++++
 platform/linux-dpdk/source/odp_packet_io.c         | 561 +++++++++++++++++++++
 platform/linux-dpdk/source/odp_queue.c             | 435 ++++++++++++++++
 18 files changed, 3005 insertions(+)
 create mode 100644 platform/linux-dpdk/Makefile
 create mode 100644 platform/linux-dpdk/Makefile.inc
 create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h
 create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h
 create mode 100644 platform/linux-dpdk/include/api/odp_packet.h
 create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h
 create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h
 create mode 100644 platform/linux-dpdk/include/odp_buffer_pool_internal.h
 create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h
 create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h
 create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h
 create mode 100644 platform/linux-dpdk/source/odp_buffer.c
 create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c
 create mode 100644 platform/linux-dpdk/source/odp_init.c
 create mode 100644 platform/linux-dpdk/source/odp_packet.c
 create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c
 create mode 100644 platform/linux-dpdk/source/odp_packet_io.c
 create mode 100644 platform/linux-dpdk/source/odp_queue.c

Comments

Mike Holmes July 11, 2014, 7:44 p.m. UTC | #1
Adds whitespace errors when applied.
Also needs a README like the one in linux-keystone to indicate such things
as setting ./configure --with-platform=linux-dpdk
And how to then ensure  dpdk is installed to resolve things like
/usr/include/stdc-predef.h:59:1: fatal error:
../../../dpdk/build/include/rte_config.h: No such file or directory


On 11 July 2014 14:35, <venkatesh.vivekanandan@linaro.org> wrote:

> From: Vincent Hsu <vincent.hsu@linaro.org>
>
> Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org>
> ---
>  platform/linux-dpdk/Makefile                       | 158 ++++++
>  platform/linux-dpdk/Makefile.inc                   |   7 +
>  platform/linux-dpdk/include/api/odp_buffer.h       | 101 ++++
>  platform/linux-dpdk/include/api/odp_buffer_pool.h  |  99 ++++
>  platform/linux-dpdk/include/api/odp_packet.h       | 228 +++++++++
>  platform/linux-dpdk/include/api/odp_pktio_types.h  |  45 ++
>  platform/linux-dpdk/include/odp_buffer_internal.h  |  79 +++
>  .../linux-dpdk/include/odp_buffer_pool_internal.h  |  90 ++++
>  platform/linux-dpdk/include/odp_packet_dpdk.h      |  88 ++++
>  platform/linux-dpdk/include/odp_packet_internal.h  | 140 +++++
>  .../linux-dpdk/include/odp_packet_io_internal.h    |  52 ++
>  platform/linux-dpdk/source/odp_buffer.c            | 102 ++++
>  platform/linux-dpdk/source/odp_buffer_pool.c       | 156 ++++++
>  platform/linux-dpdk/source/odp_init.c              | 113 +++++
>  platform/linux-dpdk/source/odp_packet.c            | 374 ++++++++++++++
>  platform/linux-dpdk/source/odp_packet_dpdk.c       | 177 +++++++
>  platform/linux-dpdk/source/odp_packet_io.c         | 561
> +++++++++++++++++++++
>  platform/linux-dpdk/source/odp_queue.c             | 435 ++++++++++++++++
>  18 files changed, 3005 insertions(+)
>  create mode 100644 platform/linux-dpdk/Makefile
>  create mode 100644 platform/linux-dpdk/Makefile.inc
>  create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h
>  create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h
>  create mode 100644 platform/linux-dpdk/include/api/odp_packet.h
>  create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h
>  create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h
>  create mode 100644 platform/linux-dpdk/include/odp_buffer_pool_internal.h
>  create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h
>  create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h
>  create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h
>  create mode 100644 platform/linux-dpdk/source/odp_buffer.c
>  create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c
>  create mode 100644 platform/linux-dpdk/source/odp_init.c
>  create mode 100644 platform/linux-dpdk/source/odp_packet.c
>  create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c
>  create mode 100644 platform/linux-dpdk/source/odp_packet_io.c
>  create mode 100644 platform/linux-dpdk/source/odp_queue.c
>
> diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile
> new file mode 100644
> index 0000000..bf8d0b3
> --- /dev/null
> +++ b/platform/linux-dpdk/Makefile
> @@ -0,0 +1,158 @@
> +## Copyright (c) 2013, Linaro Limited
> +## All rights reserved.
> +##
> +## Redistribution and use in source and binary forms, with or without
> +## modification, are permitted provided that the following conditions are
> met:
> +##
> +##    * Redistributions of source code must retain the above copyright
> notice, this
> +##      list of conditions and the following disclaimer.
> +##
> +##    * Redistributions in binary form must reproduce the above copyright
> notice, this
> +##      list of conditions and the following disclaimer in the
> documentation and/or
> +##      other materials provided with the distribution.
> +##
> +##    * Neither the name of Linaro Limited nor the names of its
> contributors may be
> +##      used to endorse or promote products derived from this software
> without specific
> +##      prior written permission.
> +##
> +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS" AND
> +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> IMPLIED
> +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
> LIABLE
> +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> CONSEQUENTIAL
> +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
> GOODS OR
> +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> HOWEVER
> +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> LIABILITY,
> +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +.DEFAULT_GOAL := libs
> +
> +ODP_ROOT = ../..
> +LIB_DIR  = ./lib
> +DOC_DIR  = ./doc
> +
> +LINUX_GENERIC_DIR = ../linux-generic
> +
> +RTE_SDK    ?= $(abspath $(ODP_ROOT)/../dpdk)
> +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build)
> +RTE_LIB    ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a)
> +
> +PLAT_CFLAGS  = -include $(RTE_OUTPUT)/include/rte_config.h
> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include
> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch
> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env
> +PLAT_CFLAGS += -msse4.2
> +
> +EXTRA_CFLAGS += $(PLAT_CFLAGS)
> +EXTRA_CFLAGS += -I./include
> +EXTRA_CFLAGS += -I./include/api
> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include
> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api
> +EXTRA_CFLAGS += -I$(ODP_ROOT)/include
> +
> +include $(ODP_ROOT)/Makefile.inc
> +STATIC_LIB = ./lib/libodp.a
> +
> +#
> +# Object files
> +#
> +OBJS     =
> +OBJS    += $(OBJ_DIR)/odp_barrier.o
> +OBJS    += $(OBJ_DIR)/odp_buffer.o
> +OBJS    += $(OBJ_DIR)/odp_buffer_pool.o
> +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
> +OBJS    += $(OBJ_DIR)/odp_schedule.o
> +OBJS    += $(OBJ_DIR)/odp_shared_memory.o
> +OBJS    += $(OBJ_DIR)/odp_spinlock.o
> +OBJS    += $(OBJ_DIR)/odp_system_info.o
> +OBJS    += $(OBJ_DIR)/odp_thread.o
> +OBJS    += $(OBJ_DIR)/odp_ticketlock.o
> +OBJS    += $(OBJ_DIR)/odp_time.o
> +OBJS    += $(OBJ_DIR)/odp_timer.o
> +OBJS    += $(OBJ_DIR)/odp_ring.o
> +OBJS    += $(OBJ_DIR)/odp_rwlock.o
> +OBJS    += $(OBJ_DIR)/odp_packet_dpdk.o
> +
> +DEPS     = $(OBJS:.o=.d)
> +
> +.PHONY: all
> +all: libs docs
> +
> +-include $(DEPS)
> +
> +#$(OBJ_DIR):
> +#      $(MKDIR) $(OBJ_DIR)
> +
> +$(LIB_DIR):
> +       $(MKDIR) $(LIB_DIR)
> +
> +$(DOC_DIR):
> +       $(MKDIR) $(DOC_DIR)/html
> +       $(MKDIR) $(DOC_DIR)/latex
> +
> +#
> +# Compile rules
> +#
> +vpath %.c source:$(LINUX_GENERIC_DIR)/source
> +
> +$(OBJ_DIR)/%.o: %.c
> +       $(ECHO) "  CC    $<"
> +       $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $<
> +
> +#
> +# Lib rule
> +#
> +$(OBJ_DIR)/libodp.o: $(OBJS)
> +       $(ECHO) "  LD    $@"
> +       $(LD) -r -o $@ $(OBJS) $(RTE_LIB)
> +
> +$(STATIC_LIB): $(OBJ_DIR)/libodp.o
> +       $(ECHO) "  AR    $@"
> +       $(AR) -cr $@ $(OBJ_DIR)/libodp.o
> +
> +
> +clean:
> +       $(RMDIR) $(OBJ_DIR)
> +       $(RMDIR) $(LIB_DIR)
> +       $(RMDIR) $(DOC_DIR)
> +       $(RM) Doxyfile
> +
> +Doxyfile: Doxyfile.in
> +       doxygen -u - < $< > $@
> +
> +.PHONY: docs
> +docs: $(DOC_DIR) Doxyfile ./include/odp*.h
> +       doxygen
> +
> +.PHONY: docs_install
> +docs_install: docs
> +       $(COPY) doc $(DESTDIR)
> +
> +.PHONY: pdf
> +pdf: docs
> +       make --directory doc/latex refman.pdf 1> /dev/null
> +
> +.PHONY: libs
> +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB)
> +
> +.PHONY: lib_install
> +lib_install: libs
> +       install -d $(DESTDIR)/lib
> +       install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/
> +
> +.PHONY: headers_install
> +headers_install: libs
> +       $(ECHO) Installing headers to $(DESTDIR)/include
> +       $(COPY) $(ODP_ROOT)/include $(DESTDIR)
> +       $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/
> +       $(COPY) include/api/* $(DESTDIR)/include/
> +
> +install: lib_install headers_install
> diff --git a/platform/linux-dpdk/Makefile.inc
> b/platform/linux-dpdk/Makefile.inc
> new file mode 100644
> index 0000000..fe7679b
> --- /dev/null
> +++ b/platform/linux-dpdk/Makefile.inc
> @@ -0,0 +1,7 @@
> +# Copyright (c) 2013, Linaro Limited
> +# All rights reserved.
> +#
> +# SPDX-License-Identifier:     BSD-3-Clause
> +
> +STD_LIBS += -ldl
> +
> diff --git a/platform/linux-dpdk/include/api/odp_buffer.h
> b/platform/linux-dpdk/include/api/odp_buffer.h
> new file mode 100644
> index 0000000..286d9e6
> --- /dev/null
> +++ b/platform/linux-dpdk/include/api/odp_buffer.h
> @@ -0,0 +1,101 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +
> +/**
> + * @file
> + *
> + * ODP buffer descriptor
> + */
> +
> +#ifndef ODP_BUFFER_H_
> +#define ODP_BUFFER_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +
> +
> +#include <odp_std_types.h>
> +
> +
> +
> +
> +
> +/**
> + * ODP buffer
> + */
> +typedef unsigned long odp_buffer_t;
> +
> +
> +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */
> +
> +
> +/**
> + * Buffer start address
> + *
> + * @param buf      Buffer handle
> + *
> + * @return Buffer start address
> + */
> +void *odp_buffer_addr(odp_buffer_t buf);
> +
> +/**
> + * Buffer maximum data size
> + *
> + * @param buf      Buffer handle
> + *
> + * @return Buffer maximum data size
> + */
> +size_t odp_buffer_size(odp_buffer_t buf);
> +
> +/**
> + * Buffer type
> + *
> + * @param buf      Buffer handle
> + *
> + * @return Buffer type
> + */
> +int odp_buffer_type(odp_buffer_t buf);
> +
> +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */
> +#define ODP_BUFFER_TYPE_RAW       0  /**< Raw buffer */
> +#define ODP_BUFFER_TYPE_PACKET    1  /**< Packet buffer */
> +#define ODP_BUFFER_TYPE_TIMER     2  /**< Timer buffer */
> +
> +/**
> + * Tests if buffer is part of a scatter/gather list
> + *
> + * @param buf      Buffer handle
> + *
> + * @return 1 if belongs to a scatter list, otherwise 0
> + */
> +int odp_buffer_is_scatter(odp_buffer_t buf);
> +
> +/**
> + * Tests if buffer is valid
> + *
> + * @param buf      Buffer handle
> + *
> + * @return 1 if valid, otherwise 0
> + */
> +int odp_buffer_is_valid(odp_buffer_t buf);
> +
> +/**
> + * Print buffer metadata to STDOUT
> + *
> + * @param buf      Buffer handle
> + *
> + */
> +void odp_buffer_print(odp_buffer_t buf);
> +
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h
> b/platform/linux-dpdk/include/api/odp_buffer_pool.h
> new file mode 100644
> index 0000000..4b75cf5
> --- /dev/null
> +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h
> @@ -0,0 +1,99 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +
> +/**
> + * @file
> + *
> + * ODP buffer pool
> + */
> +
> +#ifndef ODP_BUFFER_POOL_H_
> +#define ODP_BUFFER_POOL_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +
> +
> +#include <odp_std_types.h>
> +#include <odp_buffer.h>
> +
> +/** Maximum queue name lenght in chars */
> +#define ODP_BUFFER_POOL_NAME_LEN  32
> +
> +/** Invalid buffer pool */
> +#define ODP_BUFFER_POOL_INVALID  (0xffffffff)
> +
> +/** ODP buffer pool */
> +typedef unsigned long odp_buffer_pool_t;
> +
> +
> +/**
> + * Create a buffer pool
> + *
> + * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1
> chars)
> + * @param base_addr Pool base address
> + * @param size      Pool size in bytes
> + * @param buf_size  Buffer size in bytes
> + * @param buf_align Minimum buffer alignment
> + * @param buf_type  Buffer type
> + *
> + * @return Buffer pool handle
> + */
> +odp_buffer_pool_t odp_buffer_pool_create(const char *name,
> +                                        void *base_addr, uint64_t size,
> +                                        size_t buf_size, size_t buf_align,
> +                                        int buf_type);
> +
> +
> +/**
> + * Find a buffer pool by name
> + *
> + * @param name      Name of the pool
> + *
> + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
> + */
> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name);
> +
> +
> +/**
> + * Print buffer pool info
> + *
> + * @param pool      Pool handle
> + *
> + */
> +void odp_buffer_pool_print(odp_buffer_pool_t pool);
> +
> +
> +
> +/**
> + * Buffer alloc
> + *
> + * @param pool      Pool handle
> + *
> + * @return Buffer handle or ODP_BUFFER_INVALID
> + */
> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool);
> +
> +
> +/**
> + * Buffer free
> + *
> + * @param buf       Buffer handle
> + *
> + */
> +void odp_buffer_free(odp_buffer_t buf);
> +
> +
> +
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/platform/linux-dpdk/include/api/odp_packet.h
> b/platform/linux-dpdk/include/api/odp_packet.h
> new file mode 100644
> index 0000000..bdb3417
> --- /dev/null
> +++ b/platform/linux-dpdk/include/api/odp_packet.h
> @@ -0,0 +1,228 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +
> +/**
> + * @file
> + *
> + * ODP packet descriptor
> + */
> +
> +#ifndef ODP_PACKET_H_
> +#define ODP_PACKET_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <odp_buffer.h>
> +
> +
> +/**
> + * ODP packet descriptor
> + */
> +typedef unsigned long odp_packet_t;
> +
> +
> +/** Invalid packet */
> +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID
> +
> +/** Invalid offset */
> +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1)
> +
> +
> +/**
> + * Initialize the packet
> + *
> + * Needs to be called if the user allocates a packet buffer, i.e. the
> packet
> + * has not been received from I/O through ODP.
> + *
> + * @param pkt  Packet handle
> + */
> +void odp_packet_init(odp_packet_t pkt);
> +
> +/**
> + * Convert from packet handle to buffer handle
> + *
> + * @param buf  Buffer handle
> + *
> + * @return Packet handle
> + */
> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf);
> +
> +/**
> + * Convert from buffer handle to packet handle
> + *
> + * @param pkt  Packet handle
> + *
> + * @return Buffer handle
> + */
> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt);
> +
> +/**
> + * Set the packet length
> + *
> + * @param pkt  Packet handle
> + * @param len  Length of packet in bytes
> + */
> +void odp_packet_set_len(odp_packet_t pkt, size_t len);
> +
> +/**
> + * Get the packet length
> + *
> + * @param pkt  Packet handle
> + *
> + * @return   Packet length in bytes
> + */
> +size_t odp_packet_get_len(odp_packet_t pkt);
> +
> +/**
> + * Get address to the start of the packet buffer
> + *
> + * The address of the packet buffer is not necessarily the same as the
> start
> + * address of the received frame, e.g. an eth frame may be offset by 2 or
> 6
> + * bytes to ensure 32 or 64-bit alignment of the IP header.
> + * Use odp_packet_l2(pkt) to get the start address of a received valid
> frame
> + * or odp_packet_start(pkt) to get the start address even if no valid L2
> header
> + * could be found.
> + *
> + * @param pkt  Packet handle
> + *
> + * @return  Pointer to the start of the packet buffer
> + *
> + * @see odp_packet_l2(), odp_packet_start()
> + */
> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt);
> +
> +/**
> + * Get pointer to the start of the received frame
> + *
> + * The address of the packet buffer is not necessarily the same as the
> start
> + * address of the received frame, e.g. an eth frame may be offset by 2 or
> 6
> + * bytes to ensure 32 or 64-bit alignment of the IP header.
> + * Use odp_packet_l2(pkt) to get the start address of a received valid
> eth frame
> + *
> + * odp_packet_start() will always return a pointer to the start of the
> frame,
> + * even if the frame is unrecognized and no valid L2 header could be
> found.
> + *
> + * @param pkt  Packet handle
> + *
> + * @return  Pointer to the start of the received frame
> + *
> + * @see odp_packet_l2(), odp_packet_buf_addr()
> + */
> +uint8_t *odp_packet_start(odp_packet_t pkt);
> +
> +/**
> + * Get pointer to the start of the L2 frame
> + *
> + * The L2 frame header address is not necessarily the same as the address
> of the
> + * packet buffer, see odp_packet_buf_addr()
> + *
> + * @param pkt  Packet handle
> + *
> + * @return  Pointer to L2 header or NULL if not found
> + *
> + * @see odp_packet_buf_addr(), odp_packet_start()
> + */
> +uint8_t *odp_packet_l2(odp_packet_t pkt);
> +
> +/**
> + * Return the byte offset from the packet buffer to the L2 frame
> + *
> + * @param pkt  Packet handle
> + *
> + * @return  L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found
> + */
> +size_t odp_packet_l2_offset(odp_packet_t pkt);
> +
> +/**
> + * Set the byte offset to the L2 frame
> + *
> + * @param pkt     Packet handle
> + * @param offset  L2 byte offset
> + */
> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset);
> +
> +
> +/**
> + * Get pointer to the start of the L3 packet
> + *
> + * @param pkt  Packet handle
> + *
> + * @return  Pointer to L3 packet or NULL if not found
> + *
> + */
> +uint8_t *odp_packet_l3(odp_packet_t pkt);
> +
> +/**
> + * Return the byte offset from the packet buffer to the L3 packet
> + *
> + * @param pkt  Packet handle
> + *
> + * @return  L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found
> + */
> +size_t odp_packet_l3_offset(odp_packet_t pkt);
> +
> +/**
> + * Set the byte offset to the L3 packet
> + *
> + * @param pkt     Packet handle
> + * @param offset  L3 byte offset
> + */
> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset);
> +
> +
> +/**
> + * Get pointer to the start of the L4 packet
> + *
> + * @param pkt  Packet handle
> + *
> + * @return  Pointer to L4 packet or NULL if not found
> + *
> + */
> +uint8_t *odp_packet_l4(odp_packet_t pkt);
> +
> +/**
> + * Return the byte offset from the packet buffer to the L4 packet
> + *
> + * @param pkt  Packet handle
> + *
> + * @return  L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found
> + */
> +size_t odp_packet_l4_offset(odp_packet_t pkt);
> +
> +/**
> + * Set the byte offset to the L4 packet
> + *
> + * @param pkt     Packet handle
> + * @param offset  L4 byte offset
> + */
> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset);
> +
> +/**
> + * Print (debug) information about the packet
> + *
> + * @param pkt  Packet handle
> + */
> +void odp_packet_print(odp_packet_t pkt);
> +
> +/**
> + * Copy contents and metadata from pkt_src to pkt_dst
> + * Useful when creating copies of packets
> + *
> + * @param pkt_dst Destination packet
> + * @param pkt_src Source packet
> + *
> + * @return 0 if successful
> + */
> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h
> b/platform/linux-dpdk/include/api/odp_pktio_types.h
> new file mode 100644
> index 0000000..b23e6da
> --- /dev/null
> +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h
> @@ -0,0 +1,45 @@
> +
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#ifndef ODP_PKTIO_TYPES_H
> +#define ODP_PKTIO_TYPES_H
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* We should ensure that future enum values will never overlap, otherwise
> + * applications that want netmap suport might get in trouble if the odp
> lib
> + * was not built with netmap support and there are more types define below
> + */
> +
> +typedef enum {
> +       ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1,
> +       ODP_PKTIO_TYPE_SOCKET_MMSG,
> +       ODP_PKTIO_TYPE_SOCKET_MMAP,
> +       ODP_PKTIO_TYPE_NETMAP,
> +       ODP_PKTIO_TYPE_DPDK,
> +} odp_pktio_type_t;
> +
> +#include <odp_pktio_socket.h>
> +#ifdef ODP_HAVE_NETMAP
> +#include <odp_pktio_netmap.h>
> +#endif
> +
> +typedef union odp_pktio_params_t {
> +       odp_pktio_type_t type;
> +       socket_params_t sock_params;
> +#ifdef ODP_HAVE_NETMAP
> +       netmap_params_t nm_params;
> +#endif
> +} odp_pktio_params_t;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h
> b/platform/linux-dpdk/include/odp_buffer_internal.h
> new file mode 100644
> index 0000000..a47107c
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_buffer_internal.h
> @@ -0,0 +1,79 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +
> +/**
> + * @file
> + *
> + * ODP buffer descriptor - implementation internal
> + */
> +
> +#ifndef ODP_BUFFER_INTERNAL_H_
> +#define ODP_BUFFER_INTERNAL_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <odp_std_types.h>
> +#include <odp_atomic.h>
> +#include <odp_buffer_pool.h>
> +#include <odp_buffer.h>
> +#include <odp_debug.h>
> +#include <odp_align.h>
> +#include <rte_mbuf.h>
> +
> +/* TODO: move these to correct files */
> +
> +typedef uint64_t odp_phys_addr_t;
> +
> +#define ODP_BUFFER_MAX_INDEX     (ODP_BUFFER_MAX_BUFFERS - 2)
> +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1)
> +
> +#define ODP_BUFS_PER_CHUNK       16
> +#define ODP_BUFS_PER_SCATTER      4
> +
> +#define ODP_BUFFER_TYPE_CHUNK    0xffff
> +
> +
> +#define ODP_BUFFER_POOL_BITS   4
> +#define ODP_BUFFER_INDEX_BITS  (32 - ODP_BUFFER_POOL_BITS)
> +#define ODP_BUFFER_MAX_POOLS   (1 << ODP_BUFFER_POOL_BITS)
> +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS)
> +
> +typedef union odp_buffer_bits_t {
> +       uint32_t     u32;
> +       odp_buffer_t handle;
> +
> +       struct {
> +               uint32_t pool:ODP_BUFFER_POOL_BITS;
> +               uint32_t index:ODP_BUFFER_INDEX_BITS;
> +       };
> +} odp_buffer_bits_t;
> +
> +
> +/* forward declaration */
> +struct odp_buffer_hdr_t;
> +
> +
> +typedef struct rte_mbuf odp_buffer_hdr_t;
> +
> +
> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf);
> +
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> +
> +
> +
> +
> +
> +
> +
> diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h
> b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
> new file mode 100644
> index 0000000..1a36655
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
> @@ -0,0 +1,90 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +
> +/**
> + * @file
> + *
> + * ODP buffer pool - internal header
> + */
> +
> +#ifndef ODP_BUFFER_POOL_INTERNAL_H_
> +#define ODP_BUFFER_POOL_INTERNAL_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <odp_std_types.h>
> +#include <odp_buffer_pool.h>
> +#include <odp_buffer_internal.h>
> +#include <odp_align.h>
> +#include <odp_hints.h>
> +#include <odp_config.h>
> +#include <odp_debug.h>
> +
> +/* for DPDK */
> +#include <rte_mempool.h>
> +
> +/* Use ticketlock instead of spinlock */
> +#define POOL_USE_TICKETLOCK
> +
> +/* Extra error checks */
> +/* #define POOL_ERROR_CHECK */
> +
> +
> +#ifdef POOL_USE_TICKETLOCK
> +#include <odp_ticketlock.h>
> +#else
> +#include <odp_spinlock.h>
> +#endif
> +
> +
> +struct pool_entry_s {
> +#ifdef POOL_USE_TICKETLOCK
> +       odp_ticketlock_t        lock ODP_ALIGNED_CACHE;
> +#else
> +       odp_spinlock_t          lock ODP_ALIGNED_CACHE;
> +#endif
> +
> +       uint64_t                free_bufs;
> +       char                    name[ODP_BUFFER_POOL_NAME_LEN];
> +
> +
> +       odp_buffer_pool_t       pool ODP_ALIGNED_CACHE;
> +       uintptr_t               buf_base;
> +       size_t                  buf_size;
> +       size_t                  buf_offset;
> +       uint64_t                num_bufs;
> +       void                   *pool_base_addr;
> +       uint64_t                pool_size;
> +       size_t                  payload_size;
> +       size_t                  payload_align;
> +       int                     buf_type;
> +       size_t                  hdr_size;
> +};
> +
> +
> +extern void *pool_entry_ptr[];
> +
> +
> +static inline void *get_pool_entry(odp_buffer_pool_t pool_id)
> +{
> +       return pool_entry_ptr[pool_id];
> +}
> +
> +
> +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf)
> +{
> +       return (odp_buffer_hdr_t *)buf;
> +}
> +
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h
> b/platform/linux-dpdk/include/odp_packet_dpdk.h
> new file mode 100644
> index 0000000..0b3db08
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
> @@ -0,0 +1,88 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#ifndef ODP_PACKET_DPDK_H
> +#define ODP_PACKET_DPDK_H
> +
> +#include <stdint.h>
> +#include <net/if.h>
> +
> +#include <helper/odp_eth.h>
> +#include <helper/odp_packet_helper.h>
> +#include <odp_align.h>
> +#include <odp_debug.h>
> +#include <odp_packet.h>
> +#include <odp_packet_internal.h>
> +#include <odp_buffer_pool.h>
> +#include <odp_buffer_pool_internal.h>
> +#include <odp_buffer_internal.h>
> +#include <odp_std_types.h>
> +
> +#include <rte_config.h>
> +#include <rte_memory.h>
> +#include <rte_memzone.h>
> +#include <rte_launch.h>
> +#include <rte_tailq.h>
> +#include <rte_eal.h>
> +#include <rte_per_lcore.h>
> +#include <rte_lcore.h>
> +#include <rte_branch_prediction.h>
> +#include <rte_prefetch.h>
> +#include <rte_cycles.h>
> +#include <rte_errno.h>
> +#include <rte_debug.h>
> +#include <rte_log.h>
> +#include <rte_byteorder.h>
> +#include <rte_pci.h>
> +#include <rte_random.h>
> +#include <rte_ether.h>
> +#include <rte_ethdev.h>
> +#include <rte_hash.h>
> +#include <rte_jhash.h>
> +#include <rte_hash_crc.h>
> +
> +
> +#define ODP_DPDK_MODE_HW       0
> +#define ODP_DPDK_MODE_SW       1
> +
> +#define DPDK_BLOCKING_IO
> +
> +/** Packet socket using dpdk mmaped rings for both Rx and Tx */
> +typedef struct {
> +       odp_buffer_pool_t pool;
> +
> +       /********************************/
> +       char ifname[32];
> +       uint8_t portid;
> +       uint16_t queueid;
> +} pkt_dpdk_t;
> +
> +/**
> + * Configure an interface to work in dpdk mode
> + */
> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
> +                  odp_buffer_pool_t pool);
> +
> +/**
> + * Switch interface from dpdk mode to normal mode
> + */
> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk);
> +
> +/**
> + * Receive packets using dpdk
> + */
> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
> +                 unsigned len);
> +
> +/**
> + * Send packets using dpdk
> + */
> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
> +                 unsigned len);
> +
> +int odp_init_dpdk(void);
> +#endif
> +
> diff --git a/platform/linux-dpdk/include/odp_packet_internal.h
> b/platform/linux-dpdk/include/odp_packet_internal.h
> new file mode 100644
> index 0000000..d9057a2
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_packet_internal.h
> @@ -0,0 +1,140 @@
> +/* Copyright (c) 2014, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +
> +/**
> + * @file
> + *
> + * ODP packet descriptor - implementation internal
> + */
> +
> +#ifndef ODP_PACKET_INTERNAL_H_
> +#define ODP_PACKET_INTERNAL_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <odp_align.h>
> +#include <odp_debug.h>
> +#include <odp_buffer_internal.h>
> +#include <odp_buffer_pool_internal.h>
> +#include <odp_packet.h>
> +#include <odp_packet_io.h>
> +
> +/**
> + * Packet input & protocol flags
> + */
> +typedef union {
> +       /* All input flags */
> +       uint32_t all;
> +
> +       struct {
> +               /* 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:1;     /**< 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;
> +
> +       struct {
> +               /* 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;
> +
> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t),
> ERROR_FLAGS_SIZE_ERROR);
> +
> +/**
> + * Packet output flags
> + */
> +typedef union {
> +       /* All output flags */
> +       uint32_t all;
> +
> +       struct {
> +               /* 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 {
> +       /* common buffer header */
> +       odp_buffer_hdr_t buf_hdr;
> +
> +       input_flags_t  input_flags;
> +       error_flags_t  error_flags;
> +       output_flags_t output_flags;
> +
> +       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;
> +
> +/**
> + * Return the packet header
> + */
> +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt)
> +{
> +       return (odp_packet_hdr_t *)pkt;
> +}
> +
> +/**
> + * Parse packet and set internal metadata
> + */
> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> +
> diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h
> b/platform/linux-dpdk/include/odp_packet_io_internal.h
> new file mode 100644
> index 0000000..5948063
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
> @@ -0,0 +1,52 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +
> +/**
> + * @file
> + *
> + * ODP packet IO - implementation internal
> + */
> +
> +#ifndef ODP_PACKET_IO_INTERNAL_H_
> +#define ODP_PACKET_IO_INTERNAL_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +#include <odp_spinlock.h>
> +#include <odp_packet_socket.h>
> +#ifdef ODP_HAVE_NETMAP
> +#include <odp_packet_netmap.h>
> +#endif
> +#include <odp_packet_dpdk.h>
> +
> +struct pktio_entry {
> +       odp_spinlock_t lock;            /**< entry spinlock */
> +       int taken;                      /**< is entry taken(1) or free(0)
> */
> +       odp_queue_t inq_default;        /**< default input queue, if set */
> +       odp_queue_t outq_default;       /**< default out queue */
> +       odp_pktio_params_t params;      /**< pktio parameters */
> +       pkt_sock_t pkt_sock;            /**< using socket API for IO */
> +       pkt_sock_mmap_t pkt_sock_mmap;  /**< using socket mmap API for IO
> */
> +#ifdef ODP_HAVE_NETMAP
> +       pkt_netmap_t pkt_nm;            /**< using netmap API for IO */
> +#endif
> +       pkt_dpdk_t pkt_dpdk;            /**< using DPDK API for IO */
> +};
> +
> +typedef union {
> +       struct pktio_entry s;
> +       uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct
> pktio_entry))];
> +} pktio_entry_t;
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif
> +
> diff --git a/platform/linux-dpdk/source/odp_buffer.c
> b/platform/linux-dpdk/source/odp_buffer.c
> new file mode 100644
> index 0000000..bfb5ff6
> --- /dev/null
> +++ b/platform/linux-dpdk/source/odp_buffer.c
> @@ -0,0 +1,102 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp_buffer.h>
> +#include <odp_buffer_internal.h>
> +#include <odp_buffer_pool_internal.h>
> +
> +#include <string.h>
> +#include <stdio.h>
> +
> +
> +void *odp_buffer_addr(odp_buffer_t buf)
> +{
> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
> +
> +       return hdr->buf_addr;
> +}
> +
> +
> +size_t odp_buffer_size(odp_buffer_t buf)
> +{
> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
> +
> +       return hdr->buf_len;
> +}
> +
> +
> +int odp_buffer_type(odp_buffer_t buf)
> +{
> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
> +
> +       return hdr->type;
> +}
> +
> +
> +int odp_buffer_is_scatter(odp_buffer_t buf)
> +{
> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
> +
> +       if (hdr->refcnt == 0)
> +               return 0;
> +       else
> +               return 1;
> +}
> +
> +
> +int odp_buffer_is_valid(odp_buffer_t buf)
> +{
> +       odp_buffer_bits_t handle;
> +
> +       handle.u32 = buf;
> +
> +       return (handle.index != ODP_BUFFER_INVALID_INDEX);
> +}
> +
> +
> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf)
> +{
> +       odp_buffer_hdr_t *hdr;
> +       int len = 0;
> +
> +       if (!odp_buffer_is_valid(buf)) {
> +               printf("Buffer is not valid.\n");
> +               return len;
> +       }
> +
> +       hdr = odp_buf_to_hdr(buf);
> +
> +       len += snprintf(&str[len], n-len,
> +                       "Buffer\n");
> +       len += snprintf(&str[len], n-len,
> +                       "  pool         %"PRIu64"\n", (int64_t) hdr->pool);
> +       len += snprintf(&str[len], n-len,
> +                       "  phy_addr     %"PRIu64"\n", hdr->buf_physaddr);
> +       len += snprintf(&str[len], n-len,
> +                       "  addr         %p\n",        hdr->buf_addr);
> +       len += snprintf(&str[len], n-len,
> +                       "  size         %u\n",        hdr->buf_len);
> +       len += snprintf(&str[len], n-len,
> +                       "  ref_count    %i\n",        hdr->refcnt);
> +       len += snprintf(&str[len], n-len,
> +                       "  type         %i\n",        hdr->type);
> +
> +       return len;
> +}
> +
> +
> +void odp_buffer_print(odp_buffer_t buf)
> +{
> +       int max_len = 512;
> +       char str[max_len];
> +       int len;
> +
> +       len = odp_buffer_snprint(str, max_len-1, buf);
> +       str[len] = 0;
> +
> +       printf("\n%s\n", str);
> +}
> +
> diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c
> b/platform/linux-dpdk/source/odp_buffer_pool.c
> new file mode 100644
> index 0000000..de90275
> --- /dev/null
> +++ b/platform/linux-dpdk/source/odp_buffer_pool.c
> @@ -0,0 +1,156 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp_std_types.h>
> +#include <odp_buffer_pool.h>
> +#include <odp_buffer_pool_internal.h>
> +#include <odp_buffer_internal.h>
> +#include <odp_packet_internal.h>
> +#include <odp_shared_memory.h>
> +#include <odp_align.h>
> +#include <odp_internal.h>
> +#include <odp_config.h>
> +#include <odp_hints.h>
> +#include <odp_debug.h>
> +
> +#include <string.h>
> +#include <stdlib.h>
> +
> +/* for DPDK */
> +#include <odp_packet_dpdk.h>
> +
> +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
> +#define NB_MBUF   8192
> +
> +#ifdef POOL_USE_TICKETLOCK
> +#include <odp_ticketlock.h>
> +#define LOCK(a)      odp_ticketlock_lock(a)
> +#define UNLOCK(a)    odp_ticketlock_unlock(a)
> +#define LOCK_INIT(a) odp_ticketlock_init(a)
> +#else
> +#include <odp_spinlock.h>
> +#define LOCK(a)      odp_spinlock_lock(a)
> +#define UNLOCK(a)    odp_spinlock_unlock(a)
> +#define LOCK_INIT(a) odp_spinlock_init(a)
> +#endif
> +
> +
> +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
> +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
> +#endif
> +
> +#define NULL_INDEX ((uint32_t)-1)
> +
> +
> +typedef union pool_entry_u {
> +       struct pool_entry_s s;
> +
> +       uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct
> pool_entry_s))];
> +
> +} pool_entry_t;
> +
> +
> +typedef struct pool_table_t {
> +       pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS];
> +
> +} pool_table_t;
> +
> +
> +/* The pool table */
> +static pool_table_t *pool_tbl;
> +
> +/* Pool entry pointers (for inlining) */
> +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS];
> +
> +
> +int odp_buffer_pool_init_global(void)
> +{
> +       odp_buffer_pool_t i;
> +
> +       pool_tbl = odp_shm_reserve("odp_buffer_pools",
> +                                  sizeof(pool_table_t),
> +                                  sizeof(pool_entry_t));
> +
> +       if (pool_tbl == NULL)
> +               return -1;
> +
> +       memset(pool_tbl, 0, sizeof(pool_table_t));
> +
> +
> +       for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) {
> +               /* init locks */
> +               pool_entry_t *pool = &pool_tbl->pool[i];
> +               LOCK_INIT(&pool->s.lock);
> +               pool->s.pool = i;
> +
> +               pool_entry_ptr[i] = pool;
> +       }
> +
> +       ODP_DBG("\nBuffer pool init global\n");
> +       ODP_DBG("  pool_entry_s size     %zu\n", sizeof(struct
> pool_entry_s));
> +       ODP_DBG("  pool_entry_t size     %zu\n", sizeof(pool_entry_t));
> +       ODP_DBG("  odp_buffer_hdr_t size %zu\n", sizeof(odp_buffer_hdr_t));
> +       ODP_DBG("\n");
> +
> +       return 0;
> +}
> +
> +
> +odp_buffer_pool_t odp_buffer_pool_create(const char *name,
> +                                        void *base_addr, uint64_t size,
> +                                        size_t buf_size, size_t buf_align,
> +                                        int buf_type)
> +{
> +       struct rte_mempool *pktmbuf_pool = NULL;
> +       ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n", name,
> +               (uint64_t) base_addr, (unsigned) size,
> +               (unsigned) buf_size, (unsigned) buf_align,
> +               buf_type);
> +
> +       pktmbuf_pool =
> +               rte_mempool_create(name, NB_MBUF,
> +                                  MBUF_SIZE, 32,
> +                                  sizeof(struct rte_pktmbuf_pool_private),
> +                                  rte_pktmbuf_pool_init, NULL,
> +                                  rte_pktmbuf_init, NULL,
> +                                  rte_socket_id(), 0);
> +       if (pktmbuf_pool == NULL) {
> +               ODP_ERR("Cannot init DPDK mbuf pool\n");
> +               return -1;
> +       }
> +
> +       return (odp_buffer_pool_t) pktmbuf_pool;
> +}
> +
> +
> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name)
> +{
> +       struct rte_mempool *mp = NULL;
> +
> +       mp = rte_mempool_lookup(name);
> +       if (mp == NULL)
> +               return ODP_BUFFER_POOL_INVALID;
> +
> +       return (odp_buffer_pool_t)mp;
> +}
> +
> +
> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id)
> +{
> +       return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool
> *)pool_id);
> +}
> +
> +
> +void odp_buffer_free(odp_buffer_t buf)
> +{
> +       rte_pktmbuf_free((struct rte_mbuf *)buf);
> +}
> +
> +
> +void odp_buffer_pool_print(odp_buffer_pool_t pool_id)
> +{
> +       rte_mempool_dump((const struct rte_mempool *)pool_id);
> +}
> diff --git a/platform/linux-dpdk/source/odp_init.c
> b/platform/linux-dpdk/source/odp_init.c
> new file mode 100644
> index 0000000..ecc2066
> --- /dev/null
> +++ b/platform/linux-dpdk/source/odp_init.c
> @@ -0,0 +1,113 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp_init.h>
> +#include <odp_internal.h>
> +#include <odp_debug.h>
> +#include <odp_packet_dpdk.h>
> +
> +int odp_init_dpdk(void)
> +{
> +       int test_argc = 5;
> +       char *test_argv[6];
> +       int core_count, i, num_cores = 0;
> +       char core_mask[8];
> +
> +       core_count  = odp_sys_core_count();
> +       for (i = 0; i < core_count; i++)
> +               num_cores += (0x1 << i);
> +       sprintf(core_mask, "%x", num_cores);
> +
> +       test_argv[0] = malloc(sizeof("odp_dpdk"));
> +       strcpy(test_argv[0], "odp_dpdk");
> +       test_argv[1] = malloc(sizeof("-c"));
> +       strcpy(test_argv[1], "-c");
> +       test_argv[2] = malloc(sizeof(core_mask));
> +       strcpy(test_argv[2], core_mask);
> +       test_argv[3] = malloc(sizeof("-n"));
> +       strcpy(test_argv[3], "-n");
> +       test_argv[4] = malloc(sizeof("3"));
> +       strcpy(test_argv[4], "3");
> +
> +       if (rte_eal_init(test_argc, (char **)test_argv) < 0) {
> +               ODP_ERR("Cannot init the Intel DPDK EAL!");
> +               return -1;
> +       }
> +
> +       if (rte_pmd_init_all() < 0) {
> +               ODP_ERR("Cannot init pmd\n");
> +               return -1;
> +       }
> +
> +       if (rte_eal_pci_probe() < 0) {
> +               ODP_ERR("Cannot probe PCI\n");
> +               return -1;
> +       }
> +
> +       return 0;
> +}
> +
> +int odp_init_global(void)
> +{
> +       odp_thread_init_global();
> +
> +       odp_system_info_init();
> +
> +       if (odp_init_dpdk()) {
> +               ODP_ERR("ODP dpdk init failed.\n");
> +               return -1;
> +       }
> +
> +       if (odp_shm_init_global()) {
> +               ODP_ERR("ODP shm init failed.\n");
> +               return -1;
> +       }
> +
> +       if (odp_buffer_pool_init_global()) {
> +               ODP_ERR("ODP buffer pool init failed.\n");
> +               return -1;
> +       }
> +
> +       if (odp_queue_init_global()) {
> +               ODP_ERR("ODP queue init failed.\n");
> +               return -1;
> +       }
> +
> +       if (odp_schedule_init_global()) {
> +               ODP_ERR("ODP schedule init failed.\n");
> +               return -1;
> +       }
> +
> +       if (odp_pktio_init_global()) {
> +               ODP_ERR("ODP packet io init failed.\n");
> +               return -1;
> +       }
> +
> +       if (odp_timer_init_global()) {
> +               ODP_ERR("ODP timer init failed.\n");
> +               return -1;
> +       }
> +
> +       return 0;
> +}
> +
> +
> +int odp_init_local(int thr_id)
> +{
> +       odp_thread_init_local(thr_id);
> +
> +       if (odp_pktio_init_local()) {
> +               ODP_ERR("ODP packet io local init failed.\n");
> +               return -1;
> +       }
> +
> +       if (odp_schedule_init_local()) {
> +               ODP_ERR("ODP schedule local init failed.\n");
> +               return -1;
> +       }
> +
> +       return 0;
> +}
> diff --git a/platform/linux-dpdk/source/odp_packet.c
> b/platform/linux-dpdk/source/odp_packet.c
> new file mode 100644
> index 0000000..c34e626
> --- /dev/null
> +++ b/platform/linux-dpdk/source/odp_packet.c
> @@ -0,0 +1,374 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp_packet.h>
> +#include <odp_packet_internal.h>
> +#include <odp_hints.h>
> +#include <odp_byteorder.h>
> +
> +#include <helper/odp_eth.h>
> +#include <helper/odp_ip.h>
> +
> +#include <string.h>
> +#include <stdio.h>
> +
> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, odp_ipv4hdr_t
> *ipv4,
> +                               size_t *offset_out);
> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, odp_ipv6hdr_t
> *ipv6,
> +                               size_t *offset_out);
> +
> +void odp_packet_init(odp_packet_t pkt)
> +{
> +       odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
> +       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
> buf_hdr);
> +       uint8_t *start;
> +       size_t len;
> +
> +       start = (uint8_t *)pkt_hdr + start_offset;
> +       len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
> +       memset(start, 0, len);
> +
> +       pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
> +       pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
> +       pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
> +}
> +
> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf)
> +{
> +       return (odp_packet_t)buf;
> +}
> +
> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt)
> +{
> +       return (odp_buffer_t)pkt;
> +}
> +
> +void odp_packet_set_len(odp_packet_t pkt, size_t len)
> +{
> +       /* for rte_pktmbuf */
> +       odp_buffer_hdr_t *buf_hdr =
> odp_buf_to_hdr(odp_buffer_from_packet(pkt));
> +       buf_hdr->pkt.data_len = len;
> +
> +       odp_packet_hdr(pkt)->frame_len = len;
> +}
> +
> +size_t odp_packet_get_len(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->frame_len;
> +}
> +
> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt)
> +{
> +       return odp_buffer_addr(odp_buffer_from_packet(pkt));
> +}
> +
> +uint8_t *odp_packet_start(odp_packet_t pkt)
> +{
> +       return odp_packet_buf_addr(pkt) +
> odp_packet_hdr(pkt)->frame_offset;
> +}
> +
> +
> +uint8_t *odp_packet_l2(odp_packet_t pkt)
> +{
> +       const size_t offset = odp_packet_l2_offset(pkt);
> +
> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
> +               return NULL;
> +
> +       return odp_packet_buf_addr(pkt) + offset;
> +}
> +
> +size_t odp_packet_l2_offset(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->l2_offset;
> +}
> +
> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset)
> +{
> +       odp_packet_hdr(pkt)->l2_offset = offset;
> +}
> +
> +uint8_t *odp_packet_l3(odp_packet_t pkt)
> +{
> +       const size_t offset = odp_packet_l3_offset(pkt);
> +
> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
> +               return NULL;
> +
> +       return odp_packet_buf_addr(pkt) + offset;
> +}
> +
> +size_t odp_packet_l3_offset(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->l3_offset;
> +}
> +
> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset)
> +{
> +       odp_packet_hdr(pkt)->l3_offset = offset;
> +}
> +
> +uint8_t *odp_packet_l4(odp_packet_t pkt)
> +{
> +       const size_t offset = odp_packet_l4_offset(pkt);
> +
> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
> +               return NULL;
> +
> +       return odp_packet_buf_addr(pkt) + offset;
> +}
> +
> +size_t odp_packet_l4_offset(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->l4_offset;
> +}
> +
> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset)
> +{
> +       odp_packet_hdr(pkt)->l4_offset = offset;
> +}
> +
> +/**
> + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP
> + *
> + * Internal function: caller is resposible for passing only valid packet
> handles
> + * , lengths and offsets (usually done&called in packet input).
> + *
> + * @param pkt        Packet handle
> + * @param len        Packet length in bytes
> + * @param frame_offset  Byte offset to L2 header
> + */
> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset)
> +{
> +       odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
> +       odp_ethhdr_t *eth;
> +       odp_vlanhdr_t *vlan;
> +       odp_ipv4hdr_t *ipv4;
> +       odp_ipv6hdr_t *ipv6;
> +       uint16_t ethtype;
> +       size_t offset = 0;
> +       uint8_t ip_proto = 0;
> +
> +       pkt_hdr->input_flags.eth = 1;
> +       pkt_hdr->frame_offset = frame_offset;
> +       pkt_hdr->frame_len = len;
> +
> +       if (odp_unlikely(len < ODP_ETH_LEN_MIN)) {
> +               pkt_hdr->error_flags.frame_len = 1;
> +               return;
> +       } else if (len > ODP_ETH_LEN_MAX) {
> +               pkt_hdr->input_flags.jumbo = 1;
> +       }
> +
> +       /* Assume valid L2 header, no CRC/FCS check in SW */
> +       pkt_hdr->input_flags.l2 = 1;
> +       pkt_hdr->l2_offset = frame_offset;
> +
> +       eth = (odp_ethhdr_t *)odp_packet_start(pkt);
> +       ethtype = odp_be_to_cpu_16(eth->type);
> +       vlan = (odp_vlanhdr_t *)&eth->type;
> +
> +       if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
> +               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->input_flags.vlan = 1;
> +               ethtype = odp_be_to_cpu_16(vlan->tpid);
> +               offset += sizeof(odp_vlanhdr_t);
> +       }
> +
> +       /* Set l3_offset+flag only for known ethtypes */
> +       switch (ethtype) {
> +       case ODP_ETHTYPE_IPV4:
> +               pkt_hdr->input_flags.ipv4 = 1;
> +               pkt_hdr->input_flags.l3 = 1;
> +               pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN +
> offset;
> +               ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
> +               ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset);
> +               break;
> +       case ODP_ETHTYPE_IPV6:
> +               pkt_hdr->input_flags.ipv6 = 1;
> +               pkt_hdr->input_flags.l3 = 1;
> +               pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN +
> offset;
> +               ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt);
> +               ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset);
> +               break;
> +       case ODP_ETHTYPE_ARP:
> +               pkt_hdr->input_flags.arp = 1;
> +               /* fall through */
> +       default:
> +               ip_proto = 0;
> +               break;
> +       }
> +
> +       switch (ip_proto) {
> +       case ODP_IPPROTO_UDP:
> +               pkt_hdr->input_flags.udp = 1;
> +               pkt_hdr->input_flags.l4 = 1;
> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
> +               break;
> +       case ODP_IPPROTO_TCP:
> +               pkt_hdr->input_flags.tcp = 1;
> +               pkt_hdr->input_flags.l4 = 1;
> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
> +               break;
> +       case ODP_IPPROTO_SCTP:
> +               pkt_hdr->input_flags.sctp = 1;
> +               pkt_hdr->input_flags.l4 = 1;
> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
> +               break;
> +       case ODP_IPPROTO_ICMP:
> +               pkt_hdr->input_flags.icmp = 1;
> +               pkt_hdr->input_flags.l4 = 1;
> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
> +               break;
> +       default:
> +               /* 0 or unhandled IP protocols, don't set L4 flag+offset */
> +               if (pkt_hdr->input_flags.ipv6) {
> +                       /* IPv6 next_hdr is not L4, mark as IP-option
> instead */
> +                       pkt_hdr->input_flags.ipopt = 1;
> +               }
> +               break;
> +       }
> +}
> +
> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, odp_ipv4hdr_t
> *ipv4,
> +                               size_t *offset_out)
> +{
> +       uint8_t ihl;
> +       uint16_t frag_offset;
> +
> +       ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl);
> +       if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) {
> +               pkt_hdr->error_flags.ip_err = 1;
> +               return 0;
> +       }
> +
> +       if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) {
> +               pkt_hdr->input_flags.ipopt = 1;
> +               return 0;
> +       }
> +
> +       /* A packet is a fragment if:
> +       *  "more fragments" flag is set (all fragments except the last)
> +       *     OR
> +       *  "fragment offset" field is nonzero (all fragments except the
> first)
> +       */
> +       frag_offset = odp_be_to_cpu_16(ipv4->frag_offset);
> +       if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) {
> +               pkt_hdr->input_flags.ipfrag = 1;
> +               return 0;
> +       }
> +
> +       if (ipv4->proto == ODP_IPPROTO_ESP ||
> +           ipv4->proto == ODP_IPPROTO_AH) {
> +               pkt_hdr->input_flags.ipsec = 1;
> +               return 0;
> +       }
> +
> +       /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after
> return */
> +
> +       *offset_out = sizeof(uint32_t) * ihl;
> +       return ipv4->proto;
> +}
> +
> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, odp_ipv6hdr_t
> *ipv6,
> +                               size_t *offset_out)
> +{
> +       if (ipv6->next_hdr == ODP_IPPROTO_ESP ||
> +           ipv6->next_hdr == ODP_IPPROTO_AH) {
> +               pkt_hdr->input_flags.ipopt = 1;
> +               pkt_hdr->input_flags.ipsec = 1;
> +               return 0;
> +       }
> +
> +       if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) {
> +               pkt_hdr->input_flags.ipopt = 1;
> +               pkt_hdr->input_flags.ipfrag = 1;
> +               return 0;
> +       }
> +
> +       /* Don't step through more extensions */
> +       *offset_out = ODP_IPV6HDR_LEN;
> +       return ipv6->next_hdr;
> +}
> +
> +void odp_packet_print(odp_packet_t pkt)
> +{
> +       int max_len = 512;
> +       char str[max_len];
> +       int len = 0;
> +       int n = max_len-1;
> +       odp_packet_hdr_t *hdr = odp_packet_hdr(pkt);
> +
> +       len += snprintf(&str[len], n-len, "Packet ");
> +       len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt);
> +       len += snprintf(&str[len], n-len,
> +                       "  input_flags  0x%x\n", hdr->input_flags.all);
> +       len += snprintf(&str[len], n-len,
> +                       "  error_flags  0x%x\n", hdr->error_flags.all);
> +       len += snprintf(&str[len], n-len,
> +                       "  output_flags 0x%x\n", hdr->output_flags.all);
> +       len += snprintf(&str[len], n-len,
> +                       "  frame_offset %u\n", hdr->frame_offset);
> +       len += snprintf(&str[len], n-len,
> +                       "  l2_offset    %u\n", hdr->l2_offset);
> +       len += snprintf(&str[len], n-len,
> +                       "  l3_offset    %u\n", hdr->l3_offset);
> +       len += snprintf(&str[len], n-len,
> +                       "  l4_offset    %u\n", hdr->l4_offset);
> +       len += snprintf(&str[len], n-len,
> +                       "  frame_len    %u\n", hdr->frame_len);
> +       len += snprintf(&str[len], n-len,
> +                       "  input        %u\n", hdr->input);
> +       str[len] = '\0';
> +
> +       printf("\n%s\n", str);
> +}
> +
> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src)
> +{
> +       odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst);
> +       odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src);
> +       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
> buf_hdr);
> +       uint8_t *start_src;
> +       uint8_t *start_dst;
> +       size_t len;
> +
> +       if (pkt_dst == ODP_PACKET_INVALID || pkt_src == ODP_PACKET_INVALID)
> +               return -1;
> +
> +       /* if (pkt_hdr_dst->buf_hdr.size < */
> +       /*      pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */
> +       if (pkt_hdr_dst->buf_hdr.buf_len <
> +               pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset)
> +               return -1;
> +
> +       /* Copy packet header */
> +       start_dst = (uint8_t *)pkt_hdr_dst + start_offset;
> +       start_src = (uint8_t *)pkt_hdr_src + start_offset;
> +       len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
> +       memcpy(start_dst, start_src, len);
> +
> +       /* Copy frame payload */
> +       start_dst = (uint8_t *)odp_packet_start(pkt_dst);
> +       start_src = (uint8_t *)odp_packet_start(pkt_src);
> +       len = pkt_hdr_src->frame_len;
> +       memcpy(start_dst, start_src, len);
> +
> +       /* Copy useful things from the buffer header */
> +       /* pkt_hdr_dst->buf_hdr.cur_offset =
> pkt_hdr_src->buf_hdr.cur_offset; */
> +
> +       /* Create a copy of the scatter list */
> +       /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */
> +       /*                      odp_buffer_from_packet(pkt_src)); */
> +
> +       return 0;
> +}
> diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c
> b/platform/linux-dpdk/source/odp_packet_dpdk.c
> new file mode 100644
> index 0000000..6d16bbe
> --- /dev/null
> +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c
> @@ -0,0 +1,177 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <errno.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <poll.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +#include <string.h>
> +#include <stdlib.h>
> +
> +#include <linux/ethtool.h>
> +#include <linux/sockios.h>
> +
> +#include <odp_hints.h>
> +#include <odp_thread.h>
> +
> +#include <odp_packet_dpdk.h>
> +#include <net/if.h>
> +
> +/*
> + * RX and TX Prefetch, Host, and Write-back threshold values should be
> + * carefully set for optimal performance. Consult the network
> + * controller's datasheet and supporting DPDK documentation for guidance
> + * on how these parameters should be set.
> + */
> +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
> +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
> +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg.
> */
> +
> +/*
> + * These default values are optimized for use with the Intel(R) 82599 10
> GbE
> + * Controller and the DPDK ixgbe PMD. Consider using other values for
> other
> + * network controllers and/or network drivers.
> + */
> +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */
> +#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
> +#define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg.
> */
> +
> +#define MAX_PKT_BURST 32
> +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
> +#define RTE_TEST_RX_DESC_DEFAULT 128
> +#define RTE_TEST_TX_DESC_DEFAULT 512
> +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
> +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
> +
> +static const struct rte_eth_conf port_conf = {
> +       .rxmode = {
> +               .split_hdr_size = 0,
> +               .header_split   = 0, /**< Header Split disabled */
> +               .hw_ip_checksum = 0, /**< IP checksum offload disabled */
> +               .hw_vlan_filter = 0, /**< VLAN filtering disabled */
> +               .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
> +               .hw_strip_crc   = 0, /**< CRC stripped by hardware */
> +       },
> +       .txmode = {
> +               .mq_mode = ETH_MQ_TX_NONE,
> +       },
> +};
> +
> +static const struct rte_eth_rxconf rx_conf = {
> +       .rx_thresh = {
> +               .pthresh = RX_PTHRESH,
> +               .hthresh = RX_HTHRESH,
> +               .wthresh = RX_WTHRESH,
> +       },
> +};
> +
> +static const struct rte_eth_txconf tx_conf = {
> +       .tx_thresh = {
> +               .pthresh = TX_PTHRESH,
> +               .hthresh = TX_HTHRESH,
> +               .wthresh = TX_WTHRESH,
> +       },
> +       .tx_free_thresh = 0, /* Use PMD default values */
> +       .tx_rs_thresh = 0, /* Use PMD default values */
> +       /*
> +        * As the example won't handle mult-segments and offload cases,
> +        * set the flag by default.
> +        */
> +       .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS,
> +};
> +
> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
> +               odp_buffer_pool_t pool)
> +{
> +       ODP_DBG("setup_pkt_dpdk\n");
> +
> +       static struct ether_addr eth_addr[RTE_MAX_ETHPORTS];
> +       uint8_t portid = 0;
> +       uint16_t queueid = 0;
> +       int ret;
> +       printf("vincent netdev: %s\n", netdev);
> +       printf("vincent pool: %lx\n", pool);
> +
> +       portid = atoi(netdev);
> +       pkt_dpdk->portid = portid;
> +       pkt_dpdk->queueid = queueid;
> +       pkt_dpdk->pool = pool;
> +       printf("vincent portid: %u\n", portid);
> +
> +       fflush(stdout);
> +       ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
> +       if (ret < 0)
> +               ODP_ERR("Cannot configure device: err=%d, port=%u\n",
> +                       ret, (unsigned) portid);
> +
> +       rte_eth_macaddr_get(portid, &eth_addr[portid]);
> +       ODP_DBG("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
> +               (unsigned) portid,
> +               eth_addr[portid].addr_bytes[0],
> +               eth_addr[portid].addr_bytes[1],
> +               eth_addr[portid].addr_bytes[2],
> +               eth_addr[portid].addr_bytes[3],
> +               eth_addr[portid].addr_bytes[4],
> +               eth_addr[portid].addr_bytes[5]);
> +
> +       /* init one RX queue on each port */
> +       fflush(stdout);
> +       ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
> +                                    rte_eth_dev_socket_id(portid),
> &rx_conf,
> +                                    (struct rte_mempool *)pool);
> +       if (ret < 0)
> +               ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n",
> +                       ret, (unsigned) portid);
> +       ODP_DBG("dpdk rx queue setup done\n");
> +
> +       /* init one TX queue on each port */
> +       fflush(stdout);
> +       ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
> +                       rte_eth_dev_socket_id(portid), &tx_conf);
> +       if (ret < 0)
> +               ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n",
> +                       ret, (unsigned) portid);
> +       ODP_DBG("dpdk tx queue setup done\n");
> +
> +       /* Start device */
> +       ret = rte_eth_dev_start(portid);
> +       if (ret < 0)
> +               ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n",
> +                       ret, (unsigned) portid);
> +       ODP_DBG("dpdk setup done\n\n");
> +
> +
> +       return 0;
> +}
> +
> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk)
> +{
> +       ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid);
> +
> +       return 0;
> +}
> +
> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
> +               unsigned len)
> +{
> +       return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid,
> +                               (uint16_t)pkt_dpdk->queueid,
> +                               (struct rte_mbuf **)pkt_table,
> (uint16_t)len);
> +}
> +
> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
> +               unsigned len)
> +{
> +       return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid,
> +                               (uint16_t)pkt_dpdk->queueid,
> +                               (struct rte_mbuf **)pkt_table,
> (uint16_t)len);
> +}
> diff --git a/platform/linux-dpdk/source/odp_packet_io.c
> b/platform/linux-dpdk/source/odp_packet_io.c
> new file mode 100644
> index 0000000..abea0ec
> --- /dev/null
> +++ b/platform/linux-dpdk/source/odp_packet_io.c
> @@ -0,0 +1,561 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp_packet_io.h>
> +#include <odp_packet_io_internal.h>
> +#include <odp_packet_io_queue.h>
> +#include <odp_packet.h>
> +#include <odp_packet_internal.h>
> +#include <odp_internal.h>
> +#include <odp_spinlock.h>
> +#include <odp_shared_memory.h>
> +#include <odp_packet_socket.h>
> +#ifdef ODP_HAVE_NETMAP
> +#include <odp_packet_netmap.h>
> +#endif
> +#include <odp_hints.h>
> +#include <odp_config.h>
> +#include <odp_queue_internal.h>
> +#include <odp_schedule_internal.h>
> +#include <odp_debug.h>
> +
> +#include <odp_pktio_socket.h>
> +#ifdef ODP_HAVE_NETMAP
> +#include <odp_pktio_netmap.h>
> +#endif
> +
> +#include <string.h>
> +
> +typedef struct {
> +       pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
> +} pktio_table_t;
> +
> +static pktio_table_t *pktio_tbl;
> +
> +
> +static pktio_entry_t *get_entry(odp_pktio_t id)
> +{
> +       if (odp_unlikely(id == ODP_PKTIO_INVALID ||
> +                        id > ODP_CONFIG_PKTIO_ENTRIES))
> +               return NULL;
> +
> +       return &pktio_tbl->entries[id - 1];
> +}
> +
> +int odp_pktio_init_global(void)
> +{
> +       char name[ODP_QUEUE_NAME_LEN];
> +       pktio_entry_t *pktio_entry;
> +       queue_entry_t *queue_entry;
> +       odp_queue_t qid;
> +       int id;
> +
> +       pktio_tbl = odp_shm_reserve("odp_pktio_entries",
> +                                   sizeof(pktio_table_t),
> +                                   sizeof(pktio_entry_t));
> +       if (pktio_tbl == NULL)
> +               return -1;
> +
> +       memset(pktio_tbl, 0, sizeof(pktio_table_t));
> +
> +       for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
> +               pktio_entry = get_entry(id);
> +
> +               odp_spinlock_init(&pktio_entry->s.lock);
> +
> +               /* Create a default output queue for each pktio resource */
> +               snprintf(name, sizeof(name), "%i-pktio_outq_default",
> (int)id);
> +               name[ODP_QUEUE_NAME_LEN-1] = '\0';
> +
> +               qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, NULL);
> +               if (qid == ODP_QUEUE_INVALID)
> +                       return -1;
> +               pktio_entry->s.outq_default = qid;
> +
> +               queue_entry = queue_to_qentry(qid);
> +               queue_entry->s.pktout = id;
> +       }
> +
> +       return 0;
> +}
> +
> +int odp_pktio_init_local(void)
> +{
> +       return 0;
> +}
> +
> +static int is_free(pktio_entry_t *entry)
> +{
> +       return (entry->s.taken == 0);
> +}
> +
> +static void set_free(pktio_entry_t *entry)
> +{
> +       entry->s.taken = 0;
> +}
> +
> +static void set_taken(pktio_entry_t *entry)
> +{
> +       entry->s.taken = 1;
> +}
> +
> +static void lock_entry(pktio_entry_t *entry)
> +{
> +       odp_spinlock_lock(&entry->s.lock);
> +}
> +
> +static void unlock_entry(pktio_entry_t *entry)
> +{
> +       odp_spinlock_unlock(&entry->s.lock);
> +}
> +
> +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t
> *params)
> +{
> +       set_taken(entry);
> +       entry->s.inq_default = ODP_QUEUE_INVALID;
> +       switch (params->type) {
> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
> +               memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock));
> +               memset(&entry->s.pkt_sock_mmap, 0,
> +                      sizeof(entry->s.pkt_sock_mmap));
> +               break;
> +#ifdef ODP_HAVE_NETMAP
> +       case ODP_PKTIO_TYPE_NETMAP:
> +               memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm));
> +               break;
> +#endif
> +       case ODP_PKTIO_TYPE_DPDK:
> +               memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk));
> +               break;
> +       default:
> +               ODP_ERR("Packet I/O type not supported. Please
> recompile\n");
> +               break;
> +       }
> +       /* Save pktio parameters, type is the most useful */
> +       memcpy(&entry->s.params, params, sizeof(*params));
> +}
> +
> +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
> +{
> +       odp_pktio_t id;
> +       pktio_entry_t *entry;
> +       int i;
> +
> +       for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
> +               entry = &pktio_tbl->entries[i];
> +               if (is_free(entry)) {
> +                       lock_entry(entry);
> +                       if (is_free(entry)) {
> +                               init_pktio_entry(entry, params);
> +                               id = i + 1;
> +                               return id; /* return with entry locked! */
> +                       }
> +                       unlock_entry(entry);
> +               }
> +       }
> +
> +       return ODP_PKTIO_INVALID;
> +}
> +
> +static int free_pktio_entry(odp_pktio_t id)
> +{
> +       pktio_entry_t *entry = get_entry(id);
> +
> +       if (entry == NULL)
> +               return -1;
> +
> +       set_free(entry);
> +
> +       return 0;
> +}
> +
> +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
> +                          odp_pktio_params_t *params)
> +{
> +       odp_pktio_t id;
> +       pktio_entry_t *pktio_entry;
> +       int res;
> +
> +       if (params == NULL) {
> +               ODP_ERR("Invalid pktio params\n");
> +               return ODP_PKTIO_INVALID;
> +       }
> +
> +       switch (params->type) {
> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
> +               ODP_DBG("Allocating socket pktio\n");
> +               break;
> +#ifdef ODP_HAVE_NETMAP
> +       case ODP_PKTIO_TYPE_NETMAP:
> +               ODP_DBG("Allocating netmap pktio\n");
> +               break;
> +#endif
> +       case ODP_PKTIO_TYPE_DPDK:
> +               ODP_DBG("Allocating dpdk pktio\n");
> +               break;
> +       default:
> +               ODP_ERR("Invalid pktio type: %02x\n", params->type);
> +               return ODP_PKTIO_INVALID;
> +       }
> +
> +       id = alloc_lock_pktio_entry(params);
> +       if (id == ODP_PKTIO_INVALID) {
> +               ODP_ERR("No resources available.\n");
> +               return ODP_PKTIO_INVALID;
> +       }
> +       /* if successful, alloc_pktio_entry() returns with the entry
> locked */
> +
> +       pktio_entry = get_entry(id);
> +
> +       switch (params->type) {
> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
> +               res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, pool);
> +               if (res == -1) {
> +                       close_pkt_sock(&pktio_entry->s.pkt_sock);
> +                       free_pktio_entry(id);
> +                       id = ODP_PKTIO_INVALID;
> +               }
> +               break;
> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
> +               res = setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
> dev,
> +                               pool, params->sock_params.fanout);
> +               if (res == -1) {
> +                       close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap);
> +                       free_pktio_entry(id);
> +                       id = ODP_PKTIO_INVALID;
> +               }
> +               break;
> +#ifdef ODP_HAVE_NETMAP
> +       case ODP_PKTIO_TYPE_NETMAP:
> +
> +               res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev,
> +                               pool, &params->nm_params);
> +               if (res == -1) {
> +                       close_pkt_netmap(&pktio_entry->s.pkt_nm);
> +                       free_pktio_entry(id);
> +                       id = ODP_PKTIO_INVALID;
> +               }
> +               break;
> +#endif
> +       case ODP_PKTIO_TYPE_DPDK:
> +               res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, pool);
> +               if (res == -1) {
> +                       close_pkt_dpdk(&pktio_entry->s.pkt_dpdk);
> +                       free_pktio_entry(id);
> +                       id = ODP_PKTIO_INVALID;
> +               }
> +               break;
> +       default:
> +               free_pktio_entry(id);
> +               id = ODP_PKTIO_INVALID;
> +               ODP_ERR("Invalid pktio type. Please recompile.\n");
> +               break;
> +       }
> +
> +       unlock_entry(pktio_entry);
> +       return id;
> +}
> +
> +int odp_pktio_close(odp_pktio_t id)
> +{
> +       pktio_entry_t *entry;
> +       int res = -1;
> +
> +       entry = get_entry(id);
> +       if (entry == NULL)
> +               return -1;
> +
> +       lock_entry(entry);
> +       if (!is_free(entry)) {
> +               switch (entry->s.params.type) {
> +               case ODP_PKTIO_TYPE_SOCKET_BASIC:
> +               case ODP_PKTIO_TYPE_SOCKET_MMSG:
> +                       res  = close_pkt_sock(&entry->s.pkt_sock);
> +                       break;
> +               case ODP_PKTIO_TYPE_SOCKET_MMAP:
> +                       res  =
> close_pkt_sock_mmap(&entry->s.pkt_sock_mmap);
> +                       break;
> +#ifdef ODP_HAVE_NETMAP
> +               case ODP_PKTIO_TYPE_NETMAP:
> +                       res  = close_pkt_netmap(&entry->s.pkt_nm);
> +                       break;
> +#endif
> +               case ODP_PKTIO_TYPE_DPDK:
> +                       res  = close_pkt_dpdk(&entry->s.pkt_dpdk);
> +                       break;
> +               default:
> +                       break;
> +               res |= free_pktio_entry(id);
> +               }
> +       }
> +       unlock_entry(entry);
> +
> +       if (res != 0)
> +               return -1;
> +
> +       return 0;
> +}
> +
> +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio)
> +{
> +       odp_packet_hdr(pkt)->input = pktio;
> +}
> +
> +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt)
> +{
> +       return odp_packet_hdr(pkt)->input;
> +}
> +
> +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
> +{
> +       pktio_entry_t *pktio_entry = get_entry(id);
> +       int pkts;
> +       int i;
> +
> +       if (pktio_entry == NULL)
> +               return -1;
> +
> +       lock_entry(pktio_entry);
> +       switch (pktio_entry->s.params.type) {
> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
> +               pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock,
> +                               pkt_table, len);
> +               break;
> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
> +               pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
> +                               pkt_table, len);
> +               break;
> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
> +               pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
> +                               pkt_table, len);
> +               break;
> +#ifdef ODP_HAVE_NETMAP
> +       case ODP_PKTIO_TYPE_NETMAP:
> +               pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm, pkt_table,
> len);
> +               break;
> +#endif
> +       case ODP_PKTIO_TYPE_DPDK:
> +               pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table,
> len);
> +               break;
> +       default:
> +               pkts = -1;
> +               break;
> +       }
> +
> +       unlock_entry(pktio_entry);
> +       if (pkts < 0)
> +               return pkts;
> +
> +       for (i = 0; i < pkts; ++i)
> +               odp_pktio_set_input(pkt_table[i], id);
> +
> +       return pkts;
> +}
> +
> +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
> +{
> +       pktio_entry_t *pktio_entry = get_entry(id);
> +       int pkts;
> +
> +       if (pktio_entry == NULL)
> +               return -1;
> +
> +       lock_entry(pktio_entry);
> +       switch (pktio_entry->s.params.type) {
> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
> +               pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock,
> +                               pkt_table, len);
> +               break;
> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
> +               pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
> +                               pkt_table, len);
> +               break;
> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
> +               pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
> +                               pkt_table, len);
> +               break;
> +#ifdef ODP_HAVE_NETMAP
> +       case ODP_PKTIO_TYPE_NETMAP:
> +               pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm,
> +                               pkt_table, len);
> +               break;
> +#endif
> +       case ODP_PKTIO_TYPE_DPDK:
> +               pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk,
> +                               pkt_table, len);
> +               break;
> +       default:
> +               pkts = -1;
> +       }
> +       unlock_entry(pktio_entry);
> +
> +       return pkts;
> +}
> +
> +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue)
> +{
> +       pktio_entry_t *pktio_entry = get_entry(id);
> +       queue_entry_t *qentry = queue_to_qentry(queue);
> +
> +       if (pktio_entry == NULL || qentry == NULL)
> +               return -1;
> +
> +       if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN)
> +               return -1;
> +
> +       lock_entry(pktio_entry);
> +       pktio_entry->s.inq_default = queue;
> +       unlock_entry(pktio_entry);
> +
> +       queue_lock(qentry);
> +       qentry->s.pktin = id;
> +       qentry->s.status = QUEUE_STATUS_SCHED;
> +       queue_unlock(qentry);
> +
> +       odp_schedule_queue(queue, qentry->s.param.sched.prio);
> +
> +       return 0;
> +}
> +
> +int odp_pktio_inq_remdef(odp_pktio_t id)
> +{
> +       return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID);
> +}
> +
> +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
> +{
> +       pktio_entry_t *pktio_entry = get_entry(id);
> +
> +       if (pktio_entry == NULL)
> +               return ODP_QUEUE_INVALID;
> +
> +       return pktio_entry->s.inq_default;
> +}
> +
> +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
> +{
> +       pktio_entry_t *pktio_entry = get_entry(id);
> +
> +       if (pktio_entry == NULL)
> +               return ODP_QUEUE_INVALID;
> +
> +       return pktio_entry->s.outq_default;
> +}
> +
> +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
> +{
> +       odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t) buf_hdr);
> +       int len = 1;
> +       int nbr;
> +
> +       nbr = odp_pktio_send(qentry->s.pktout, &pkt, len);
> +       return (nbr == len ? 0 : -1);
> +}
> +
> +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry)
> +{
> +       (void)qentry;
> +       return NULL;
> +}
> +
> +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
> +                    int num)
> +{
> +       odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
> +       int nbr;
> +       int i;
> +
> +       for (i = 0; i < num; ++i)
> +               pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t)
> buf_hdr[i]);
> +
> +       nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num);
> +       return (nbr == num ? 0 : -1);
> +}
> +
> +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
> +                    int num)
> +{
> +       (void)qentry;
> +       (void)buf_hdr;
> +       (void)num;
> +
> +       return 0;
> +}
> +
> +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
> +{
> +       /* Use default action */
> +       return queue_enq(qentry, buf_hdr);
> +}
> +
> +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
> +{
> +       odp_buffer_hdr_t *buf_hdr;
> +
> +       buf_hdr = queue_deq(qentry);
> +
> +       if (buf_hdr == NULL) {
> +               odp_packet_t pkt;
> +               odp_buffer_t buf;
> +               odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
> +               odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
> +               int pkts, i, j;
> +
> +               pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
> +                                     QUEUE_MULTI_MAX);
> +
> +               if (pkts > 0) {
> +                       pkt = pkt_tbl[0];
> +                       buf = odp_buffer_from_packet(pkt);
> +                       buf_hdr = odp_buf_to_hdr(buf);
> +
> +                       for (i = 1, j = 0; i < pkts; ++i) {
> +                               buf = odp_buffer_from_packet(pkt_tbl[i]);
> +                               tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf);
> +                       }
> +                       queue_enq_multi(qentry, tmp_hdr_tbl, j);
> +               }
> +       }
> +
> +       return buf_hdr;
> +}
> +
> +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
> int num)
> +{
> +       /* Use default action */
> +       return queue_enq_multi(qentry, buf_hdr, num);
> +}
> +
> +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
> int num)
> +{
> +       int nbr;
> +
> +       nbr = queue_deq_multi(qentry, buf_hdr, num);
> +
> +       if (nbr < num) {
> +               odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
> +               odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
> +               odp_buffer_t buf;
> +               int pkts, i;
> +
> +               pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
> +                                     QUEUE_MULTI_MAX);
> +               if (pkts > 0) {
> +                       for (i = 0; i < pkts; ++i) {
> +                               buf = odp_buffer_from_packet(pkt_tbl[i]);
> +                               tmp_hdr_tbl[i] = odp_buf_to_hdr(buf);
> +                       }
> +                       queue_enq_multi(qentry, tmp_hdr_tbl, pkts);
> +               }
> +       }
> +
> +       return nbr;
> +}
> diff --git a/platform/linux-dpdk/source/odp_queue.c
> b/platform/linux-dpdk/source/odp_queue.c
> new file mode 100644
> index 0000000..554b8ea
> --- /dev/null
> +++ b/platform/linux-dpdk/source/odp_queue.c
> @@ -0,0 +1,435 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <odp_queue.h>
> +#include <odp_queue_internal.h>
> +#include <odp_std_types.h>
> +#include <odp_align.h>
> +#include <odp_buffer.h>
> +#include <odp_buffer_internal.h>
> +#include <odp_buffer_pool_internal.h>
> +#include <odp_internal.h>
> +#include <odp_shared_memory.h>
> +#include <odp_schedule_internal.h>
> +#include <odp_config.h>
> +#include <odp_packet_io_internal.h>
> +#include <odp_packet_io_queue.h>
> +#include <odp_debug.h>
> +#include <odp_hints.h>
> +
> +#ifdef USE_TICKETLOCK
> +#include <odp_ticketlock.h>
> +#define LOCK(a)      odp_ticketlock_lock(a)
> +#define UNLOCK(a)    odp_ticketlock_unlock(a)
> +#define LOCK_INIT(a) odp_ticketlock_init(a)
> +#else
> +#include <odp_spinlock.h>
> +#define LOCK(a)      odp_spinlock_lock(a)
> +#define UNLOCK(a)    odp_spinlock_unlock(a)
> +#define LOCK_INIT(a) odp_spinlock_init(a)
> +#endif
> +
> +#include <string.h>
> +
> +
> +typedef struct queue_table_t {
> +       queue_entry_t  queue[ODP_CONFIG_QUEUES];
> +} queue_table_t;
> +
> +static queue_table_t *queue_tbl;
> +
> +
> +queue_entry_t *get_qentry(uint32_t queue_id)
> +{
> +       return &queue_tbl->queue[queue_id];
> +}
> +
> +static void queue_init(queue_entry_t *queue, const char *name,
> +                      odp_queue_type_t type, odp_queue_param_t *param)
> +{
> +       strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1);
> +       queue->s.type = type;
> +
> +       if (param) {
> +               memcpy(&queue->s.param, param, sizeof(odp_queue_param_t));
> +       } else {
> +               /* Defaults */
> +               memset(&queue->s.param, 0, sizeof(odp_queue_param_t));
> +               queue->s.param.sched.prio  = ODP_SCHED_PRIO_DEFAULT;
> +               queue->s.param.sched.sync  = ODP_SCHED_SYNC_DEFAULT;
> +               queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT;
> +       }
> +
> +       switch (type) {
> +       case ODP_QUEUE_TYPE_PKTIN:
> +               queue->s.enqueue = pktin_enqueue;
> +               queue->s.dequeue = pktin_dequeue;
> +               queue->s.enqueue_multi = pktin_enq_multi;
> +               queue->s.dequeue_multi = pktin_deq_multi;
> +               break;
> +       case ODP_QUEUE_TYPE_PKTOUT:
> +               queue->s.enqueue = pktout_enqueue;
> +               queue->s.dequeue = pktout_dequeue;
> +               queue->s.enqueue_multi = pktout_enq_multi;
> +               queue->s.dequeue_multi = pktout_deq_multi;
> +               break;
> +       default:
> +               queue->s.enqueue = queue_enq;
> +               queue->s.dequeue = queue_deq;
> +               queue->s.enqueue_multi = queue_enq_multi;
> +               queue->s.dequeue_multi = queue_deq_multi;
> +               break;
> +       }
> +
> +       queue->s.head = NULL;
> +       queue->s.tail = NULL;
> +       queue->s.sched_buf = ODP_BUFFER_INVALID;
> +}
> +
> +
> +int odp_queue_init_global(void)
> +{
> +       uint32_t i;
> +
> +       ODP_DBG("Queue init ... ");
> +
> +       queue_tbl = odp_shm_reserve("odp_queues",
> +                                   sizeof(queue_table_t),
> +                                   sizeof(queue_entry_t));
> +
> +       if (queue_tbl == NULL)
> +               return -1;
> +
> +       memset(queue_tbl, 0, sizeof(queue_table_t));
> +
> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
> +               /* init locks */
> +               queue_entry_t *queue = get_qentry(i);
> +               LOCK_INIT(&queue->s.lock);
> +               queue->s.handle = queue_from_id(i);
> +       }
> +
> +       ODP_DBG("done\n");
> +       ODP_DBG("Queue init global\n");
> +       ODP_DBG("  struct queue_entry_s size %zu\n",
> +               sizeof(struct queue_entry_s));
> +       ODP_DBG("  queue_entry_t size        %zu\n",
> +               sizeof(queue_entry_t));
> +       ODP_DBG("\n");
> +
> +       return 0;
> +}
> +
> +odp_queue_type_t odp_queue_type(odp_queue_t handle)
> +{
> +       queue_entry_t *queue;
> +
> +       queue = queue_to_qentry(handle);
> +
> +       return queue->s.type;
> +}
> +
> +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle)
> +{
> +       queue_entry_t *queue;
> +
> +       queue = queue_to_qentry(handle);
> +
> +       return queue->s.param.sched.sync;
> +}
> +
> +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
> +                            odp_queue_param_t *param)
> +{
> +       uint32_t i;
> +       queue_entry_t *queue;
> +       odp_queue_t handle = ODP_QUEUE_INVALID;
> +
> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
> +               queue = &queue_tbl->queue[i];
> +
> +               if (queue->s.status != QUEUE_STATUS_FREE)
> +                       continue;
> +
> +               LOCK(&queue->s.lock);
> +               if (queue->s.status == QUEUE_STATUS_FREE) {
> +                       queue_init(queue, name, type, param);
> +
> +                       if (type == ODP_QUEUE_TYPE_SCHED ||
> +                           type == ODP_QUEUE_TYPE_PKTIN)
> +                               queue->s.status = QUEUE_STATUS_NOTSCHED;
> +                       else
> +                               queue->s.status = QUEUE_STATUS_READY;
> +
> +                       handle = queue->s.handle;
> +                       UNLOCK(&queue->s.lock);
> +                       break;
> +               }
> +               UNLOCK(&queue->s.lock);
> +       }
> +
> +       if (handle != ODP_QUEUE_INVALID &&
> +           (type == ODP_QUEUE_TYPE_SCHED || type ==
> ODP_QUEUE_TYPE_PKTIN)) {
> +               odp_buffer_t buf;
> +
> +               buf = odp_schedule_buffer_alloc(handle);
> +               if (buf == ODP_BUFFER_INVALID) {
> +                       ODP_ERR("queue_init: sched buf alloc failed\n");
> +                       return ODP_QUEUE_INVALID;
> +               }
> +
> +               queue->s.sched_buf = buf;
> +               odp_schedule_mask_set(handle, queue->s.param.sched.prio);
> +       }
> +
> +       return handle;
> +}
> +
> +
> +odp_buffer_t queue_sched_buf(odp_queue_t handle)
> +{
> +       queue_entry_t *queue;
> +       queue = queue_to_qentry(handle);
> +
> +       return queue->s.sched_buf;
> +}
> +
> +
> +int queue_sched_atomic(odp_queue_t handle)
> +{
> +       queue_entry_t *queue;
> +       queue = queue_to_qentry(handle);
> +
> +       return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC;
> +}
> +
> +
> +odp_queue_t odp_queue_lookup(const char *name)
> +{
> +       uint32_t i;
> +
> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
> +               queue_entry_t *queue = &queue_tbl->queue[i];
> +
> +               if (queue->s.status == QUEUE_STATUS_FREE)
> +                       continue;
> +
> +               LOCK(&queue->s.lock);
> +               if (strcmp(name, queue->s.name) == 0) {
> +                       /* found it */
> +                       UNLOCK(&queue->s.lock);
> +                       return queue->s.handle;
> +               }
> +               UNLOCK(&queue->s.lock);
> +       }
> +
> +       return ODP_QUEUE_INVALID;
> +}
> +
> +
> +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
> +{
> +       int sched = 0;
> +
> +       LOCK(&queue->s.lock);
> +       if (queue->s.head == NULL) {
> +               /* Empty queue */
> +               queue->s.head = buf_hdr;
> +               queue->s.tail = buf_hdr;
> +               buf_hdr->pkt.next = NULL;
> +       } else {
> +               queue->s.tail->pkt.next = buf_hdr;
> +               queue->s.tail = buf_hdr;
> +               buf_hdr->pkt.next = NULL;
> +       }
> +
> +       if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
> +               queue->s.status = QUEUE_STATUS_SCHED;
> +               sched = 1; /* retval: schedule queue */
> +       }
> +       UNLOCK(&queue->s.lock);
> +
> +       /* Add queue to scheduling */
> +       if (sched == 1)
> +               odp_schedule_queue(queue->s.handle,
> queue->s.param.sched.prio);
> +
> +       return 0;
> +}
> +
> +
> +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
> int num)
> +{
> +       int sched = 0;
> +       int i;
> +       odp_buffer_hdr_t *tail;
> +
> +       for (i = 0; i < num - 1; i++)
> +               buf_hdr[i]->pkt.next = buf_hdr[i+1];
> +
> +       tail = buf_hdr[num-1];
> +       buf_hdr[num-1]->pkt.next = NULL;
> +
> +       LOCK(&queue->s.lock);
> +       /* Empty queue */
> +       if (queue->s.head == NULL)
> +               queue->s.head = buf_hdr[0];
> +       else
> +               queue->s.tail->pkt.next = buf_hdr[0];
> +
> +       queue->s.tail = tail;
> +
> +       if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
> +               queue->s.status = QUEUE_STATUS_SCHED;
> +               sched = 1; /* retval: schedule queue */
> +       }
> +       UNLOCK(&queue->s.lock);
> +
> +       /* Add queue to scheduling */
> +       if (sched == 1)
> +               odp_schedule_queue(queue->s.handle,
> queue->s.param.sched.prio);
> +
> +       return 0;
> +}
> +
> +
> +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int num)
> +{
> +       odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
> +       queue_entry_t *queue;
> +       int i;
> +
> +       if (num > QUEUE_MULTI_MAX)
> +               num = QUEUE_MULTI_MAX;
> +
> +       queue = queue_to_qentry(handle);
> +
> +       for (i = 0; i < num; i++)
> +               buf_hdr[i] = odp_buf_to_hdr(buf[i]);
> +
> +       return queue->s.enqueue_multi(queue, buf_hdr, num);
> +}
> +
> +
> +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf)
> +{
> +       odp_buffer_hdr_t *buf_hdr;
> +       queue_entry_t *queue;
> +
> +       queue   = queue_to_qentry(handle);
> +       buf_hdr = odp_buf_to_hdr(buf);
> +
> +       return queue->s.enqueue(queue, buf_hdr);
> +}
> +
> +
> +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
> +{
> +       odp_buffer_hdr_t *buf_hdr = NULL;
> +
> +       LOCK(&queue->s.lock);
> +
> +       if (queue->s.head == NULL) {
> +               /* Already empty queue */
> +               if (queue->s.status == QUEUE_STATUS_SCHED &&
> +                   queue->s.type != ODP_QUEUE_TYPE_PKTIN)
> +                       queue->s.status = QUEUE_STATUS_NOTSCHED;
> +       } else {
> +               buf_hdr       = queue->s.head;
> +               queue->s.head = buf_hdr->pkt.next;
> +               buf_hdr->pkt.next = NULL;
> +
> +               if (queue->s.head == NULL) {
> +                       /* Queue is now empty */
> +                       queue->s.tail = NULL;
> +               }
> +       }
> +
> +       UNLOCK(&queue->s.lock);
> +
> +       return buf_hdr;
> +}
> +
> +
> +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
> int num)
> +{
> +       int i = 0;
> +
> +       LOCK(&queue->s.lock);
> +
> +       if (queue->s.head == NULL) {
> +               /* Already empty queue */
> +               if (queue->s.status == QUEUE_STATUS_SCHED &&
> +                   queue->s.type != ODP_QUEUE_TYPE_PKTIN)
> +                       queue->s.status = QUEUE_STATUS_NOTSCHED;
> +       } else {
> +               odp_buffer_hdr_t *hdr = queue->s.head;
> +
> +               for (; i < num && hdr; i++) {
> +                       buf_hdr[i]       = hdr;
> +                       /* odp_prefetch(hdr->addr); */
> +                       hdr              = hdr->pkt.next;
> +                       buf_hdr[i]->pkt.next = NULL;
> +               }
> +
> +               queue->s.head = hdr;
> +
> +               if (hdr == NULL) {
> +                       /* Queue is now empty */
> +                       queue->s.tail = NULL;
> +               }
> +       }
> +
> +       UNLOCK(&queue->s.lock);
> +
> +       return i;
> +}
> +
> +
> +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int num)
> +{
> +       queue_entry_t *queue;
> +       odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
> +       int i, ret;
> +
> +       if (num > QUEUE_MULTI_MAX)
> +               num = QUEUE_MULTI_MAX;
> +
> +       queue = queue_to_qentry(handle);
> +
> +       ret = queue->s.dequeue_multi(queue, buf_hdr, num);
> +
> +       for (i = 0; i < ret; i++)
> +               buf[i] = (odp_buffer_t) buf_hdr[i];
> +
> +       return ret;
> +}
> +
> +
> +odp_buffer_t odp_queue_deq(odp_queue_t handle)
> +{
> +       queue_entry_t *queue;
> +       odp_buffer_hdr_t *buf_hdr;
> +
> +       queue   = queue_to_qentry(handle);
> +       buf_hdr = queue->s.dequeue(queue);
> +
> +       if (buf_hdr)
> +               return (odp_buffer_t) buf_hdr;
> +
> +       return ODP_BUFFER_INVALID;
> +}
> +
> +
> +void queue_lock(queue_entry_t *queue)
> +{
> +       LOCK(&queue->s.lock);
> +}
> +
> +
> +void queue_unlock(queue_entry_t *queue)
> +{
> +       UNLOCK(&queue->s.lock);
> +}
> --
> 1.9.1
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>
Venkatesh Vivekanandan July 12, 2014, 8:20 a.m. UTC | #2
On 12 July 2014 01:14, Mike Holmes <mike.holmes@linaro.org> wrote:

> Adds whitespace errors when applied.
>

Ran checkpatch.pl before submitting the patch. Please point to the
error/warning if any.


> Also needs a README like the one in linux-keystone to indicate such things
> as setting ./configure --with-platform=linux-dpdk
> And how to then ensure  dpdk is installed to resolve things like
>

Forgot to mention that prerequisite is, dpdk should be checked out and
compiled. I will probably add it in a README and send out a patch for that.


> /usr/include/stdc-predef.h:59:1: fatal error:
> ../../../dpdk/build/include/rte_config.h: No such file or directory
>

>
> On 11 July 2014 14:35, <venkatesh.vivekanandan@linaro.org> wrote:
>
>> From: Vincent Hsu <vincent.hsu@linaro.org>
>>
>> Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org>
>> ---
>>  platform/linux-dpdk/Makefile                       | 158 ++++++
>>  platform/linux-dpdk/Makefile.inc                   |   7 +
>>  platform/linux-dpdk/include/api/odp_buffer.h       | 101 ++++
>>  platform/linux-dpdk/include/api/odp_buffer_pool.h  |  99 ++++
>>  platform/linux-dpdk/include/api/odp_packet.h       | 228 +++++++++
>>  platform/linux-dpdk/include/api/odp_pktio_types.h  |  45 ++
>>  platform/linux-dpdk/include/odp_buffer_internal.h  |  79 +++
>>  .../linux-dpdk/include/odp_buffer_pool_internal.h  |  90 ++++
>>  platform/linux-dpdk/include/odp_packet_dpdk.h      |  88 ++++
>>  platform/linux-dpdk/include/odp_packet_internal.h  | 140 +++++
>>  .../linux-dpdk/include/odp_packet_io_internal.h    |  52 ++
>>  platform/linux-dpdk/source/odp_buffer.c            | 102 ++++
>>  platform/linux-dpdk/source/odp_buffer_pool.c       | 156 ++++++
>>  platform/linux-dpdk/source/odp_init.c              | 113 +++++
>>  platform/linux-dpdk/source/odp_packet.c            | 374 ++++++++++++++
>>  platform/linux-dpdk/source/odp_packet_dpdk.c       | 177 +++++++
>>  platform/linux-dpdk/source/odp_packet_io.c         | 561
>> +++++++++++++++++++++
>>  platform/linux-dpdk/source/odp_queue.c             | 435 ++++++++++++++++
>>  18 files changed, 3005 insertions(+)
>>  create mode 100644 platform/linux-dpdk/Makefile
>>  create mode 100644 platform/linux-dpdk/Makefile.inc
>>  create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h
>>  create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h
>>  create mode 100644 platform/linux-dpdk/include/api/odp_packet.h
>>  create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h
>>  create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h
>>  create mode 100644 platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>  create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h
>>  create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h
>>  create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h
>>  create mode 100644 platform/linux-dpdk/source/odp_buffer.c
>>  create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c
>>  create mode 100644 platform/linux-dpdk/source/odp_init.c
>>  create mode 100644 platform/linux-dpdk/source/odp_packet.c
>>  create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c
>>  create mode 100644 platform/linux-dpdk/source/odp_packet_io.c
>>  create mode 100644 platform/linux-dpdk/source/odp_queue.c
>>
>> diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile
>> new file mode 100644
>> index 0000000..bf8d0b3
>> --- /dev/null
>> +++ b/platform/linux-dpdk/Makefile
>> @@ -0,0 +1,158 @@
>> +## Copyright (c) 2013, Linaro Limited
>> +## All rights reserved.
>> +##
>> +## Redistribution and use in source and binary forms, with or without
>> +## modification, are permitted provided that the following conditions
>> are met:
>> +##
>> +##    * Redistributions of source code must retain the above copyright
>> notice, this
>> +##      list of conditions and the following disclaimer.
>> +##
>> +##    * Redistributions in binary form must reproduce the above
>> copyright notice, this
>> +##      list of conditions and the following disclaimer in the
>> documentation and/or
>> +##      other materials provided with the distribution.
>> +##
>> +##    * Neither the name of Linaro Limited nor the names of its
>> contributors may be
>> +##      used to endorse or promote products derived from this software
>> without specific
>> +##      prior written permission.
>> +##
>> +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>> "AS IS" AND
>> +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
>> IMPLIED
>> +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>> +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
>> LIABLE
>> +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
>> CONSEQUENTIAL
>> +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
>> GOODS OR
>> +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
>> HOWEVER
>> +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
>> LIABILITY,
>> +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
>> THE USE
>> +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>> +
>> +.DEFAULT_GOAL := libs
>> +
>> +ODP_ROOT = ../..
>> +LIB_DIR  = ./lib
>> +DOC_DIR  = ./doc
>> +
>> +LINUX_GENERIC_DIR = ../linux-generic
>> +
>> +RTE_SDK    ?= $(abspath $(ODP_ROOT)/../dpdk)
>> +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build)
>> +RTE_LIB    ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a)
>> +
>> +PLAT_CFLAGS  = -include $(RTE_OUTPUT)/include/rte_config.h
>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include
>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch
>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env
>> +PLAT_CFLAGS += -msse4.2
>> +
>> +EXTRA_CFLAGS += $(PLAT_CFLAGS)
>> +EXTRA_CFLAGS += -I./include
>> +EXTRA_CFLAGS += -I./include/api
>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include
>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api
>> +EXTRA_CFLAGS += -I$(ODP_ROOT)/include
>> +
>> +include $(ODP_ROOT)/Makefile.inc
>> +STATIC_LIB = ./lib/libodp.a
>> +
>> +#
>> +# Object files
>> +#
>> +OBJS     =
>> +OBJS    += $(OBJ_DIR)/odp_barrier.o
>> +OBJS    += $(OBJ_DIR)/odp_buffer.o
>> +OBJS    += $(OBJ_DIR)/odp_buffer_pool.o
>> +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
>> +OBJS    += $(OBJ_DIR)/odp_schedule.o
>> +OBJS    += $(OBJ_DIR)/odp_shared_memory.o
>> +OBJS    += $(OBJ_DIR)/odp_spinlock.o
>> +OBJS    += $(OBJ_DIR)/odp_system_info.o
>> +OBJS    += $(OBJ_DIR)/odp_thread.o
>> +OBJS    += $(OBJ_DIR)/odp_ticketlock.o
>> +OBJS    += $(OBJ_DIR)/odp_time.o
>> +OBJS    += $(OBJ_DIR)/odp_timer.o
>> +OBJS    += $(OBJ_DIR)/odp_ring.o
>> +OBJS    += $(OBJ_DIR)/odp_rwlock.o
>> +OBJS    += $(OBJ_DIR)/odp_packet_dpdk.o
>> +
>> +DEPS     = $(OBJS:.o=.d)
>> +
>> +.PHONY: all
>> +all: libs docs
>> +
>> +-include $(DEPS)
>> +
>> +#$(OBJ_DIR):
>> +#      $(MKDIR) $(OBJ_DIR)
>> +
>> +$(LIB_DIR):
>> +       $(MKDIR) $(LIB_DIR)
>> +
>> +$(DOC_DIR):
>> +       $(MKDIR) $(DOC_DIR)/html
>> +       $(MKDIR) $(DOC_DIR)/latex
>> +
>> +#
>> +# Compile rules
>> +#
>> +vpath %.c source:$(LINUX_GENERIC_DIR)/source
>> +
>> +$(OBJ_DIR)/%.o: %.c
>> +       $(ECHO) "  CC    $<"
>> +       $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $<
>> +
>> +#
>> +# Lib rule
>> +#
>> +$(OBJ_DIR)/libodp.o: $(OBJS)
>> +       $(ECHO) "  LD    $@"
>> +       $(LD) -r -o $@ $(OBJS) $(RTE_LIB)
>> +
>> +$(STATIC_LIB): $(OBJ_DIR)/libodp.o
>> +       $(ECHO) "  AR    $@"
>> +       $(AR) -cr $@ $(OBJ_DIR)/libodp.o
>> +
>> +
>> +clean:
>> +       $(RMDIR) $(OBJ_DIR)
>> +       $(RMDIR) $(LIB_DIR)
>> +       $(RMDIR) $(DOC_DIR)
>> +       $(RM) Doxyfile
>> +
>> +Doxyfile: Doxyfile.in
>> +       doxygen -u - < $< > $@
>> +
>> +.PHONY: docs
>> +docs: $(DOC_DIR) Doxyfile ./include/odp*.h
>> +       doxygen
>> +
>> +.PHONY: docs_install
>> +docs_install: docs
>> +       $(COPY) doc $(DESTDIR)
>> +
>> +.PHONY: pdf
>> +pdf: docs
>> +       make --directory doc/latex refman.pdf 1> /dev/null
>> +
>> +.PHONY: libs
>> +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB)
>> +
>> +.PHONY: lib_install
>> +lib_install: libs
>> +       install -d $(DESTDIR)/lib
>> +       install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/
>> +
>> +.PHONY: headers_install
>> +headers_install: libs
>> +       $(ECHO) Installing headers to $(DESTDIR)/include
>> +       $(COPY) $(ODP_ROOT)/include $(DESTDIR)
>> +       $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/
>> +       $(COPY) include/api/* $(DESTDIR)/include/
>> +
>> +install: lib_install headers_install
>> diff --git a/platform/linux-dpdk/Makefile.inc
>> b/platform/linux-dpdk/Makefile.inc
>> new file mode 100644
>> index 0000000..fe7679b
>> --- /dev/null
>> +++ b/platform/linux-dpdk/Makefile.inc
>> @@ -0,0 +1,7 @@
>> +# Copyright (c) 2013, Linaro Limited
>> +# All rights reserved.
>> +#
>> +# SPDX-License-Identifier:     BSD-3-Clause
>> +
>> +STD_LIBS += -ldl
>> +
>> diff --git a/platform/linux-dpdk/include/api/odp_buffer.h
>> b/platform/linux-dpdk/include/api/odp_buffer.h
>> new file mode 100644
>> index 0000000..286d9e6
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/api/odp_buffer.h
>> @@ -0,0 +1,101 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +
>> +/**
>> + * @file
>> + *
>> + * ODP buffer descriptor
>> + */
>> +
>> +#ifndef ODP_BUFFER_H_
>> +#define ODP_BUFFER_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +
>> +
>> +#include <odp_std_types.h>
>> +
>> +
>> +
>> +
>> +
>> +/**
>> + * ODP buffer
>> + */
>> +typedef unsigned long odp_buffer_t;
>> +
>> +
>> +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */
>> +
>> +
>> +/**
>> + * Buffer start address
>> + *
>> + * @param buf      Buffer handle
>> + *
>> + * @return Buffer start address
>> + */
>> +void *odp_buffer_addr(odp_buffer_t buf);
>> +
>> +/**
>> + * Buffer maximum data size
>> + *
>> + * @param buf      Buffer handle
>> + *
>> + * @return Buffer maximum data size
>> + */
>> +size_t odp_buffer_size(odp_buffer_t buf);
>> +
>> +/**
>> + * Buffer type
>> + *
>> + * @param buf      Buffer handle
>> + *
>> + * @return Buffer type
>> + */
>> +int odp_buffer_type(odp_buffer_t buf);
>> +
>> +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */
>> +#define ODP_BUFFER_TYPE_RAW       0  /**< Raw buffer */
>> +#define ODP_BUFFER_TYPE_PACKET    1  /**< Packet buffer */
>> +#define ODP_BUFFER_TYPE_TIMER     2  /**< Timer buffer */
>> +
>> +/**
>> + * Tests if buffer is part of a scatter/gather list
>> + *
>> + * @param buf      Buffer handle
>> + *
>> + * @return 1 if belongs to a scatter list, otherwise 0
>> + */
>> +int odp_buffer_is_scatter(odp_buffer_t buf);
>> +
>> +/**
>> + * Tests if buffer is valid
>> + *
>> + * @param buf      Buffer handle
>> + *
>> + * @return 1 if valid, otherwise 0
>> + */
>> +int odp_buffer_is_valid(odp_buffer_t buf);
>> +
>> +/**
>> + * Print buffer metadata to STDOUT
>> + *
>> + * @param buf      Buffer handle
>> + *
>> + */
>> +void odp_buffer_print(odp_buffer_t buf);
>> +
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h
>> b/platform/linux-dpdk/include/api/odp_buffer_pool.h
>> new file mode 100644
>> index 0000000..4b75cf5
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h
>> @@ -0,0 +1,99 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +
>> +/**
>> + * @file
>> + *
>> + * ODP buffer pool
>> + */
>> +
>> +#ifndef ODP_BUFFER_POOL_H_
>> +#define ODP_BUFFER_POOL_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +
>> +
>> +#include <odp_std_types.h>
>> +#include <odp_buffer.h>
>> +
>> +/** Maximum queue name lenght in chars */
>> +#define ODP_BUFFER_POOL_NAME_LEN  32
>> +
>> +/** Invalid buffer pool */
>> +#define ODP_BUFFER_POOL_INVALID  (0xffffffff)
>> +
>> +/** ODP buffer pool */
>> +typedef unsigned long odp_buffer_pool_t;
>> +
>> +
>> +/**
>> + * Create a buffer pool
>> + *
>> + * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1
>> chars)
>> + * @param base_addr Pool base address
>> + * @param size      Pool size in bytes
>> + * @param buf_size  Buffer size in bytes
>> + * @param buf_align Minimum buffer alignment
>> + * @param buf_type  Buffer type
>> + *
>> + * @return Buffer pool handle
>> + */
>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name,
>> +                                        void *base_addr, uint64_t size,
>> +                                        size_t buf_size, size_t
>> buf_align,
>> +                                        int buf_type);
>> +
>> +
>> +/**
>> + * Find a buffer pool by name
>> + *
>> + * @param name      Name of the pool
>> + *
>> + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
>> + */
>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name);
>> +
>> +
>> +/**
>> + * Print buffer pool info
>> + *
>> + * @param pool      Pool handle
>> + *
>> + */
>> +void odp_buffer_pool_print(odp_buffer_pool_t pool);
>> +
>> +
>> +
>> +/**
>> + * Buffer alloc
>> + *
>> + * @param pool      Pool handle
>> + *
>> + * @return Buffer handle or ODP_BUFFER_INVALID
>> + */
>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool);
>> +
>> +
>> +/**
>> + * Buffer free
>> + *
>> + * @param buf       Buffer handle
>> + *
>> + */
>> +void odp_buffer_free(odp_buffer_t buf);
>> +
>> +
>> +
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-dpdk/include/api/odp_packet.h
>> b/platform/linux-dpdk/include/api/odp_packet.h
>> new file mode 100644
>> index 0000000..bdb3417
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/api/odp_packet.h
>> @@ -0,0 +1,228 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +
>> +/**
>> + * @file
>> + *
>> + * ODP packet descriptor
>> + */
>> +
>> +#ifndef ODP_PACKET_H_
>> +#define ODP_PACKET_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#include <odp_buffer.h>
>> +
>> +
>> +/**
>> + * ODP packet descriptor
>> + */
>> +typedef unsigned long odp_packet_t;
>> +
>> +
>> +/** Invalid packet */
>> +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID
>> +
>> +/** Invalid offset */
>> +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1)
>> +
>> +
>> +/**
>> + * Initialize the packet
>> + *
>> + * Needs to be called if the user allocates a packet buffer, i.e. the
>> packet
>> + * has not been received from I/O through ODP.
>> + *
>> + * @param pkt  Packet handle
>> + */
>> +void odp_packet_init(odp_packet_t pkt);
>> +
>> +/**
>> + * Convert from packet handle to buffer handle
>> + *
>> + * @param buf  Buffer handle
>> + *
>> + * @return Packet handle
>> + */
>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf);
>> +
>> +/**
>> + * Convert from buffer handle to packet handle
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return Buffer handle
>> + */
>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt);
>> +
>> +/**
>> + * Set the packet length
>> + *
>> + * @param pkt  Packet handle
>> + * @param len  Length of packet in bytes
>> + */
>> +void odp_packet_set_len(odp_packet_t pkt, size_t len);
>> +
>> +/**
>> + * Get the packet length
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return   Packet length in bytes
>> + */
>> +size_t odp_packet_get_len(odp_packet_t pkt);
>> +
>> +/**
>> + * Get address to the start of the packet buffer
>> + *
>> + * The address of the packet buffer is not necessarily the same as the
>> start
>> + * address of the received frame, e.g. an eth frame may be offset by 2
>> or 6
>> + * bytes to ensure 32 or 64-bit alignment of the IP header.
>> + * Use odp_packet_l2(pkt) to get the start address of a received valid
>> frame
>> + * or odp_packet_start(pkt) to get the start address even if no valid L2
>> header
>> + * could be found.
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return  Pointer to the start of the packet buffer
>> + *
>> + * @see odp_packet_l2(), odp_packet_start()
>> + */
>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt);
>> +
>> +/**
>> + * Get pointer to the start of the received frame
>> + *
>> + * The address of the packet buffer is not necessarily the same as the
>> start
>> + * address of the received frame, e.g. an eth frame may be offset by 2
>> or 6
>> + * bytes to ensure 32 or 64-bit alignment of the IP header.
>> + * Use odp_packet_l2(pkt) to get the start address of a received valid
>> eth frame
>> + *
>> + * odp_packet_start() will always return a pointer to the start of the
>> frame,
>> + * even if the frame is unrecognized and no valid L2 header could be
>> found.
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return  Pointer to the start of the received frame
>> + *
>> + * @see odp_packet_l2(), odp_packet_buf_addr()
>> + */
>> +uint8_t *odp_packet_start(odp_packet_t pkt);
>> +
>> +/**
>> + * Get pointer to the start of the L2 frame
>> + *
>> + * The L2 frame header address is not necessarily the same as the
>> address of the
>> + * packet buffer, see odp_packet_buf_addr()
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return  Pointer to L2 header or NULL if not found
>> + *
>> + * @see odp_packet_buf_addr(), odp_packet_start()
>> + */
>> +uint8_t *odp_packet_l2(odp_packet_t pkt);
>> +
>> +/**
>> + * Return the byte offset from the packet buffer to the L2 frame
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return  L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>> + */
>> +size_t odp_packet_l2_offset(odp_packet_t pkt);
>> +
>> +/**
>> + * Set the byte offset to the L2 frame
>> + *
>> + * @param pkt     Packet handle
>> + * @param offset  L2 byte offset
>> + */
>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset);
>> +
>> +
>> +/**
>> + * Get pointer to the start of the L3 packet
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return  Pointer to L3 packet or NULL if not found
>> + *
>> + */
>> +uint8_t *odp_packet_l3(odp_packet_t pkt);
>> +
>> +/**
>> + * Return the byte offset from the packet buffer to the L3 packet
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return  L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>> + */
>> +size_t odp_packet_l3_offset(odp_packet_t pkt);
>> +
>> +/**
>> + * Set the byte offset to the L3 packet
>> + *
>> + * @param pkt     Packet handle
>> + * @param offset  L3 byte offset
>> + */
>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset);
>> +
>> +
>> +/**
>> + * Get pointer to the start of the L4 packet
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return  Pointer to L4 packet or NULL if not found
>> + *
>> + */
>> +uint8_t *odp_packet_l4(odp_packet_t pkt);
>> +
>> +/**
>> + * Return the byte offset from the packet buffer to the L4 packet
>> + *
>> + * @param pkt  Packet handle
>> + *
>> + * @return  L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>> + */
>> +size_t odp_packet_l4_offset(odp_packet_t pkt);
>> +
>> +/**
>> + * Set the byte offset to the L4 packet
>> + *
>> + * @param pkt     Packet handle
>> + * @param offset  L4 byte offset
>> + */
>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset);
>> +
>> +/**
>> + * Print (debug) information about the packet
>> + *
>> + * @param pkt  Packet handle
>> + */
>> +void odp_packet_print(odp_packet_t pkt);
>> +
>> +/**
>> + * Copy contents and metadata from pkt_src to pkt_dst
>> + * Useful when creating copies of packets
>> + *
>> + * @param pkt_dst Destination packet
>> + * @param pkt_src Source packet
>> + *
>> + * @return 0 if successful
>> + */
>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h
>> b/platform/linux-dpdk/include/api/odp_pktio_types.h
>> new file mode 100644
>> index 0000000..b23e6da
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h
>> @@ -0,0 +1,45 @@
>> +
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#ifndef ODP_PKTIO_TYPES_H
>> +#define ODP_PKTIO_TYPES_H
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +/* We should ensure that future enum values will never overlap, otherwise
>> + * applications that want netmap suport might get in trouble if the odp
>> lib
>> + * was not built with netmap support and there are more types define
>> below
>> + */
>> +
>> +typedef enum {
>> +       ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1,
>> +       ODP_PKTIO_TYPE_SOCKET_MMSG,
>> +       ODP_PKTIO_TYPE_SOCKET_MMAP,
>> +       ODP_PKTIO_TYPE_NETMAP,
>> +       ODP_PKTIO_TYPE_DPDK,
>> +} odp_pktio_type_t;
>> +
>> +#include <odp_pktio_socket.h>
>> +#ifdef ODP_HAVE_NETMAP
>> +#include <odp_pktio_netmap.h>
>> +#endif
>> +
>> +typedef union odp_pktio_params_t {
>> +       odp_pktio_type_t type;
>> +       socket_params_t sock_params;
>> +#ifdef ODP_HAVE_NETMAP
>> +       netmap_params_t nm_params;
>> +#endif
>> +} odp_pktio_params_t;
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h
>> b/platform/linux-dpdk/include/odp_buffer_internal.h
>> new file mode 100644
>> index 0000000..a47107c
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/odp_buffer_internal.h
>> @@ -0,0 +1,79 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +
>> +/**
>> + * @file
>> + *
>> + * ODP buffer descriptor - implementation internal
>> + */
>> +
>> +#ifndef ODP_BUFFER_INTERNAL_H_
>> +#define ODP_BUFFER_INTERNAL_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#include <odp_std_types.h>
>> +#include <odp_atomic.h>
>> +#include <odp_buffer_pool.h>
>> +#include <odp_buffer.h>
>> +#include <odp_debug.h>
>> +#include <odp_align.h>
>> +#include <rte_mbuf.h>
>> +
>> +/* TODO: move these to correct files */
>> +
>> +typedef uint64_t odp_phys_addr_t;
>> +
>> +#define ODP_BUFFER_MAX_INDEX     (ODP_BUFFER_MAX_BUFFERS - 2)
>> +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1)
>> +
>> +#define ODP_BUFS_PER_CHUNK       16
>> +#define ODP_BUFS_PER_SCATTER      4
>> +
>> +#define ODP_BUFFER_TYPE_CHUNK    0xffff
>> +
>> +
>> +#define ODP_BUFFER_POOL_BITS   4
>> +#define ODP_BUFFER_INDEX_BITS  (32 - ODP_BUFFER_POOL_BITS)
>> +#define ODP_BUFFER_MAX_POOLS   (1 << ODP_BUFFER_POOL_BITS)
>> +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS)
>> +
>> +typedef union odp_buffer_bits_t {
>> +       uint32_t     u32;
>> +       odp_buffer_t handle;
>> +
>> +       struct {
>> +               uint32_t pool:ODP_BUFFER_POOL_BITS;
>> +               uint32_t index:ODP_BUFFER_INDEX_BITS;
>> +       };
>> +} odp_buffer_bits_t;
>> +
>> +
>> +/* forward declaration */
>> +struct odp_buffer_hdr_t;
>> +
>> +
>> +typedef struct rte_mbuf odp_buffer_hdr_t;
>> +
>> +
>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf);
>> +
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> +
>> +
>> +
>> +
>> +
>> +
>> +
>> diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>> b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>> new file mode 100644
>> index 0000000..1a36655
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>> @@ -0,0 +1,90 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +
>> +/**
>> + * @file
>> + *
>> + * ODP buffer pool - internal header
>> + */
>> +
>> +#ifndef ODP_BUFFER_POOL_INTERNAL_H_
>> +#define ODP_BUFFER_POOL_INTERNAL_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#include <odp_std_types.h>
>> +#include <odp_buffer_pool.h>
>> +#include <odp_buffer_internal.h>
>> +#include <odp_align.h>
>> +#include <odp_hints.h>
>> +#include <odp_config.h>
>> +#include <odp_debug.h>
>> +
>> +/* for DPDK */
>> +#include <rte_mempool.h>
>> +
>> +/* Use ticketlock instead of spinlock */
>> +#define POOL_USE_TICKETLOCK
>> +
>> +/* Extra error checks */
>> +/* #define POOL_ERROR_CHECK */
>> +
>> +
>> +#ifdef POOL_USE_TICKETLOCK
>> +#include <odp_ticketlock.h>
>> +#else
>> +#include <odp_spinlock.h>
>> +#endif
>> +
>> +
>> +struct pool_entry_s {
>> +#ifdef POOL_USE_TICKETLOCK
>> +       odp_ticketlock_t        lock ODP_ALIGNED_CACHE;
>> +#else
>> +       odp_spinlock_t          lock ODP_ALIGNED_CACHE;
>> +#endif
>> +
>> +       uint64_t                free_bufs;
>> +       char                    name[ODP_BUFFER_POOL_NAME_LEN];
>> +
>> +
>> +       odp_buffer_pool_t       pool ODP_ALIGNED_CACHE;
>> +       uintptr_t               buf_base;
>> +       size_t                  buf_size;
>> +       size_t                  buf_offset;
>> +       uint64_t                num_bufs;
>> +       void                   *pool_base_addr;
>> +       uint64_t                pool_size;
>> +       size_t                  payload_size;
>> +       size_t                  payload_align;
>> +       int                     buf_type;
>> +       size_t                  hdr_size;
>> +};
>> +
>> +
>> +extern void *pool_entry_ptr[];
>> +
>> +
>> +static inline void *get_pool_entry(odp_buffer_pool_t pool_id)
>> +{
>> +       return pool_entry_ptr[pool_id];
>> +}
>> +
>> +
>> +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf)
>> +{
>> +       return (odp_buffer_hdr_t *)buf;
>> +}
>> +
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h
>> b/platform/linux-dpdk/include/odp_packet_dpdk.h
>> new file mode 100644
>> index 0000000..0b3db08
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
>> @@ -0,0 +1,88 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#ifndef ODP_PACKET_DPDK_H
>> +#define ODP_PACKET_DPDK_H
>> +
>> +#include <stdint.h>
>> +#include <net/if.h>
>> +
>> +#include <helper/odp_eth.h>
>> +#include <helper/odp_packet_helper.h>
>> +#include <odp_align.h>
>> +#include <odp_debug.h>
>> +#include <odp_packet.h>
>> +#include <odp_packet_internal.h>
>> +#include <odp_buffer_pool.h>
>> +#include <odp_buffer_pool_internal.h>
>> +#include <odp_buffer_internal.h>
>> +#include <odp_std_types.h>
>> +
>> +#include <rte_config.h>
>> +#include <rte_memory.h>
>> +#include <rte_memzone.h>
>> +#include <rte_launch.h>
>> +#include <rte_tailq.h>
>> +#include <rte_eal.h>
>> +#include <rte_per_lcore.h>
>> +#include <rte_lcore.h>
>> +#include <rte_branch_prediction.h>
>> +#include <rte_prefetch.h>
>> +#include <rte_cycles.h>
>> +#include <rte_errno.h>
>> +#include <rte_debug.h>
>> +#include <rte_log.h>
>> +#include <rte_byteorder.h>
>> +#include <rte_pci.h>
>> +#include <rte_random.h>
>> +#include <rte_ether.h>
>> +#include <rte_ethdev.h>
>> +#include <rte_hash.h>
>> +#include <rte_jhash.h>
>> +#include <rte_hash_crc.h>
>> +
>> +
>> +#define ODP_DPDK_MODE_HW       0
>> +#define ODP_DPDK_MODE_SW       1
>> +
>> +#define DPDK_BLOCKING_IO
>> +
>> +/** Packet socket using dpdk mmaped rings for both Rx and Tx */
>> +typedef struct {
>> +       odp_buffer_pool_t pool;
>> +
>> +       /********************************/
>> +       char ifname[32];
>> +       uint8_t portid;
>> +       uint16_t queueid;
>> +} pkt_dpdk_t;
>> +
>> +/**
>> + * Configure an interface to work in dpdk mode
>> + */
>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
>> +                  odp_buffer_pool_t pool);
>> +
>> +/**
>> + * Switch interface from dpdk mode to normal mode
>> + */
>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk);
>> +
>> +/**
>> + * Receive packets using dpdk
>> + */
>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
>> +                 unsigned len);
>> +
>> +/**
>> + * Send packets using dpdk
>> + */
>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
>> +                 unsigned len);
>> +
>> +int odp_init_dpdk(void);
>> +#endif
>> +
>> diff --git a/platform/linux-dpdk/include/odp_packet_internal.h
>> b/platform/linux-dpdk/include/odp_packet_internal.h
>> new file mode 100644
>> index 0000000..d9057a2
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/odp_packet_internal.h
>> @@ -0,0 +1,140 @@
>> +/* Copyright (c) 2014, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +
>> +/**
>> + * @file
>> + *
>> + * ODP packet descriptor - implementation internal
>> + */
>> +
>> +#ifndef ODP_PACKET_INTERNAL_H_
>> +#define ODP_PACKET_INTERNAL_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#include <odp_align.h>
>> +#include <odp_debug.h>
>> +#include <odp_buffer_internal.h>
>> +#include <odp_buffer_pool_internal.h>
>> +#include <odp_packet.h>
>> +#include <odp_packet_io.h>
>> +
>> +/**
>> + * Packet input & protocol flags
>> + */
>> +typedef union {
>> +       /* All input flags */
>> +       uint32_t all;
>> +
>> +       struct {
>> +               /* 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:1;     /**< 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;
>> +
>> +       struct {
>> +               /* 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;
>> +
>> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t),
>> ERROR_FLAGS_SIZE_ERROR);
>> +
>> +/**
>> + * Packet output flags
>> + */
>> +typedef union {
>> +       /* All output flags */
>> +       uint32_t all;
>> +
>> +       struct {
>> +               /* 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 {
>> +       /* common buffer header */
>> +       odp_buffer_hdr_t buf_hdr;
>> +
>> +       input_flags_t  input_flags;
>> +       error_flags_t  error_flags;
>> +       output_flags_t output_flags;
>> +
>> +       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;
>> +
>> +/**
>> + * Return the packet header
>> + */
>> +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt)
>> +{
>> +       return (odp_packet_hdr_t *)pkt;
>> +}
>> +
>> +/**
>> + * Parse packet and set internal metadata
>> + */
>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> +
>> diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h
>> b/platform/linux-dpdk/include/odp_packet_io_internal.h
>> new file mode 100644
>> index 0000000..5948063
>> --- /dev/null
>> +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
>> @@ -0,0 +1,52 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +
>> +/**
>> + * @file
>> + *
>> + * ODP packet IO - implementation internal
>> + */
>> +
>> +#ifndef ODP_PACKET_IO_INTERNAL_H_
>> +#define ODP_PACKET_IO_INTERNAL_H_
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#include <odp_spinlock.h>
>> +#include <odp_packet_socket.h>
>> +#ifdef ODP_HAVE_NETMAP
>> +#include <odp_packet_netmap.h>
>> +#endif
>> +#include <odp_packet_dpdk.h>
>> +
>> +struct pktio_entry {
>> +       odp_spinlock_t lock;            /**< entry spinlock */
>> +       int taken;                      /**< is entry taken(1) or free(0)
>> */
>> +       odp_queue_t inq_default;        /**< default input queue, if set
>> */
>> +       odp_queue_t outq_default;       /**< default out queue */
>> +       odp_pktio_params_t params;      /**< pktio parameters */
>> +       pkt_sock_t pkt_sock;            /**< using socket API for IO */
>> +       pkt_sock_mmap_t pkt_sock_mmap;  /**< using socket mmap API for IO
>> */
>> +#ifdef ODP_HAVE_NETMAP
>> +       pkt_netmap_t pkt_nm;            /**< using netmap API for IO */
>> +#endif
>> +       pkt_dpdk_t pkt_dpdk;            /**< using DPDK API for IO */
>> +};
>> +
>> +typedef union {
>> +       struct pktio_entry s;
>> +       uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct
>> pktio_entry))];
>> +} pktio_entry_t;
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif
>> +
>> diff --git a/platform/linux-dpdk/source/odp_buffer.c
>> b/platform/linux-dpdk/source/odp_buffer.c
>> new file mode 100644
>> index 0000000..bfb5ff6
>> --- /dev/null
>> +++ b/platform/linux-dpdk/source/odp_buffer.c
>> @@ -0,0 +1,102 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_buffer.h>
>> +#include <odp_buffer_internal.h>
>> +#include <odp_buffer_pool_internal.h>
>> +
>> +#include <string.h>
>> +#include <stdio.h>
>> +
>> +
>> +void *odp_buffer_addr(odp_buffer_t buf)
>> +{
>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>> +
>> +       return hdr->buf_addr;
>> +}
>> +
>> +
>> +size_t odp_buffer_size(odp_buffer_t buf)
>> +{
>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>> +
>> +       return hdr->buf_len;
>> +}
>> +
>> +
>> +int odp_buffer_type(odp_buffer_t buf)
>> +{
>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>> +
>> +       return hdr->type;
>> +}
>> +
>> +
>> +int odp_buffer_is_scatter(odp_buffer_t buf)
>> +{
>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>> +
>> +       if (hdr->refcnt == 0)
>> +               return 0;
>> +       else
>> +               return 1;
>> +}
>> +
>> +
>> +int odp_buffer_is_valid(odp_buffer_t buf)
>> +{
>> +       odp_buffer_bits_t handle;
>> +
>> +       handle.u32 = buf;
>> +
>> +       return (handle.index != ODP_BUFFER_INVALID_INDEX);
>> +}
>> +
>> +
>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf)
>> +{
>> +       odp_buffer_hdr_t *hdr;
>> +       int len = 0;
>> +
>> +       if (!odp_buffer_is_valid(buf)) {
>> +               printf("Buffer is not valid.\n");
>> +               return len;
>> +       }
>> +
>> +       hdr = odp_buf_to_hdr(buf);
>> +
>> +       len += snprintf(&str[len], n-len,
>> +                       "Buffer\n");
>> +       len += snprintf(&str[len], n-len,
>> +                       "  pool         %"PRIu64"\n", (int64_t)
>> hdr->pool);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  phy_addr     %"PRIu64"\n", hdr->buf_physaddr);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  addr         %p\n",        hdr->buf_addr);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  size         %u\n",        hdr->buf_len);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  ref_count    %i\n",        hdr->refcnt);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  type         %i\n",        hdr->type);
>> +
>> +       return len;
>> +}
>> +
>> +
>> +void odp_buffer_print(odp_buffer_t buf)
>> +{
>> +       int max_len = 512;
>> +       char str[max_len];
>> +       int len;
>> +
>> +       len = odp_buffer_snprint(str, max_len-1, buf);
>> +       str[len] = 0;
>> +
>> +       printf("\n%s\n", str);
>> +}
>> +
>> diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c
>> b/platform/linux-dpdk/source/odp_buffer_pool.c
>> new file mode 100644
>> index 0000000..de90275
>> --- /dev/null
>> +++ b/platform/linux-dpdk/source/odp_buffer_pool.c
>> @@ -0,0 +1,156 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_std_types.h>
>> +#include <odp_buffer_pool.h>
>> +#include <odp_buffer_pool_internal.h>
>> +#include <odp_buffer_internal.h>
>> +#include <odp_packet_internal.h>
>> +#include <odp_shared_memory.h>
>> +#include <odp_align.h>
>> +#include <odp_internal.h>
>> +#include <odp_config.h>
>> +#include <odp_hints.h>
>> +#include <odp_debug.h>
>> +
>> +#include <string.h>
>> +#include <stdlib.h>
>> +
>> +/* for DPDK */
>> +#include <odp_packet_dpdk.h>
>> +
>> +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
>> +#define NB_MBUF   8192
>> +
>> +#ifdef POOL_USE_TICKETLOCK
>> +#include <odp_ticketlock.h>
>> +#define LOCK(a)      odp_ticketlock_lock(a)
>> +#define UNLOCK(a)    odp_ticketlock_unlock(a)
>> +#define LOCK_INIT(a) odp_ticketlock_init(a)
>> +#else
>> +#include <odp_spinlock.h>
>> +#define LOCK(a)      odp_spinlock_lock(a)
>> +#define UNLOCK(a)    odp_spinlock_unlock(a)
>> +#define LOCK_INIT(a) odp_spinlock_init(a)
>> +#endif
>> +
>> +
>> +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
>> +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
>> +#endif
>> +
>> +#define NULL_INDEX ((uint32_t)-1)
>> +
>> +
>> +typedef union pool_entry_u {
>> +       struct pool_entry_s s;
>> +
>> +       uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct
>> pool_entry_s))];
>> +
>> +} pool_entry_t;
>> +
>> +
>> +typedef struct pool_table_t {
>> +       pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS];
>> +
>> +} pool_table_t;
>> +
>> +
>> +/* The pool table */
>> +static pool_table_t *pool_tbl;
>> +
>> +/* Pool entry pointers (for inlining) */
>> +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS];
>> +
>> +
>> +int odp_buffer_pool_init_global(void)
>> +{
>> +       odp_buffer_pool_t i;
>> +
>> +       pool_tbl = odp_shm_reserve("odp_buffer_pools",
>> +                                  sizeof(pool_table_t),
>> +                                  sizeof(pool_entry_t));
>> +
>> +       if (pool_tbl == NULL)
>> +               return -1;
>> +
>> +       memset(pool_tbl, 0, sizeof(pool_table_t));
>> +
>> +
>> +       for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) {
>> +               /* init locks */
>> +               pool_entry_t *pool = &pool_tbl->pool[i];
>> +               LOCK_INIT(&pool->s.lock);
>> +               pool->s.pool = i;
>> +
>> +               pool_entry_ptr[i] = pool;
>> +       }
>> +
>> +       ODP_DBG("\nBuffer pool init global\n");
>> +       ODP_DBG("  pool_entry_s size     %zu\n", sizeof(struct
>> pool_entry_s));
>> +       ODP_DBG("  pool_entry_t size     %zu\n", sizeof(pool_entry_t));
>> +       ODP_DBG("  odp_buffer_hdr_t size %zu\n",
>> sizeof(odp_buffer_hdr_t));
>> +       ODP_DBG("\n");
>> +
>> +       return 0;
>> +}
>> +
>> +
>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name,
>> +                                        void *base_addr, uint64_t size,
>> +                                        size_t buf_size, size_t
>> buf_align,
>> +                                        int buf_type)
>> +{
>> +       struct rte_mempool *pktmbuf_pool = NULL;
>> +       ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n", name,
>> +               (uint64_t) base_addr, (unsigned) size,
>> +               (unsigned) buf_size, (unsigned) buf_align,
>> +               buf_type);
>> +
>> +       pktmbuf_pool =
>> +               rte_mempool_create(name, NB_MBUF,
>> +                                  MBUF_SIZE, 32,
>> +                                  sizeof(struct
>> rte_pktmbuf_pool_private),
>> +                                  rte_pktmbuf_pool_init, NULL,
>> +                                  rte_pktmbuf_init, NULL,
>> +                                  rte_socket_id(), 0);
>> +       if (pktmbuf_pool == NULL) {
>> +               ODP_ERR("Cannot init DPDK mbuf pool\n");
>> +               return -1;
>> +       }
>> +
>> +       return (odp_buffer_pool_t) pktmbuf_pool;
>> +}
>> +
>> +
>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name)
>> +{
>> +       struct rte_mempool *mp = NULL;
>> +
>> +       mp = rte_mempool_lookup(name);
>> +       if (mp == NULL)
>> +               return ODP_BUFFER_POOL_INVALID;
>> +
>> +       return (odp_buffer_pool_t)mp;
>> +}
>> +
>> +
>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id)
>> +{
>> +       return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool
>> *)pool_id);
>> +}
>> +
>> +
>> +void odp_buffer_free(odp_buffer_t buf)
>> +{
>> +       rte_pktmbuf_free((struct rte_mbuf *)buf);
>> +}
>> +
>> +
>> +void odp_buffer_pool_print(odp_buffer_pool_t pool_id)
>> +{
>> +       rte_mempool_dump((const struct rte_mempool *)pool_id);
>> +}
>> diff --git a/platform/linux-dpdk/source/odp_init.c
>> b/platform/linux-dpdk/source/odp_init.c
>> new file mode 100644
>> index 0000000..ecc2066
>> --- /dev/null
>> +++ b/platform/linux-dpdk/source/odp_init.c
>> @@ -0,0 +1,113 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_init.h>
>> +#include <odp_internal.h>
>> +#include <odp_debug.h>
>> +#include <odp_packet_dpdk.h>
>> +
>> +int odp_init_dpdk(void)
>> +{
>> +       int test_argc = 5;
>> +       char *test_argv[6];
>> +       int core_count, i, num_cores = 0;
>> +       char core_mask[8];
>> +
>> +       core_count  = odp_sys_core_count();
>> +       for (i = 0; i < core_count; i++)
>> +               num_cores += (0x1 << i);
>> +       sprintf(core_mask, "%x", num_cores);
>> +
>> +       test_argv[0] = malloc(sizeof("odp_dpdk"));
>> +       strcpy(test_argv[0], "odp_dpdk");
>> +       test_argv[1] = malloc(sizeof("-c"));
>> +       strcpy(test_argv[1], "-c");
>> +       test_argv[2] = malloc(sizeof(core_mask));
>> +       strcpy(test_argv[2], core_mask);
>> +       test_argv[3] = malloc(sizeof("-n"));
>> +       strcpy(test_argv[3], "-n");
>> +       test_argv[4] = malloc(sizeof("3"));
>> +       strcpy(test_argv[4], "3");
>> +
>> +       if (rte_eal_init(test_argc, (char **)test_argv) < 0) {
>> +               ODP_ERR("Cannot init the Intel DPDK EAL!");
>> +               return -1;
>> +       }
>> +
>> +       if (rte_pmd_init_all() < 0) {
>> +               ODP_ERR("Cannot init pmd\n");
>> +               return -1;
>> +       }
>> +
>> +       if (rte_eal_pci_probe() < 0) {
>> +               ODP_ERR("Cannot probe PCI\n");
>> +               return -1;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +int odp_init_global(void)
>> +{
>> +       odp_thread_init_global();
>> +
>> +       odp_system_info_init();
>> +
>> +       if (odp_init_dpdk()) {
>> +               ODP_ERR("ODP dpdk init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       if (odp_shm_init_global()) {
>> +               ODP_ERR("ODP shm init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       if (odp_buffer_pool_init_global()) {
>> +               ODP_ERR("ODP buffer pool init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       if (odp_queue_init_global()) {
>> +               ODP_ERR("ODP queue init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       if (odp_schedule_init_global()) {
>> +               ODP_ERR("ODP schedule init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       if (odp_pktio_init_global()) {
>> +               ODP_ERR("ODP packet io init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       if (odp_timer_init_global()) {
>> +               ODP_ERR("ODP timer init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +
>> +int odp_init_local(int thr_id)
>> +{
>> +       odp_thread_init_local(thr_id);
>> +
>> +       if (odp_pktio_init_local()) {
>> +               ODP_ERR("ODP packet io local init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       if (odp_schedule_init_local()) {
>> +               ODP_ERR("ODP schedule local init failed.\n");
>> +               return -1;
>> +       }
>> +
>> +       return 0;
>> +}
>> diff --git a/platform/linux-dpdk/source/odp_packet.c
>> b/platform/linux-dpdk/source/odp_packet.c
>> new file mode 100644
>> index 0000000..c34e626
>> --- /dev/null
>> +++ b/platform/linux-dpdk/source/odp_packet.c
>> @@ -0,0 +1,374 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_packet.h>
>> +#include <odp_packet_internal.h>
>> +#include <odp_hints.h>
>> +#include <odp_byteorder.h>
>> +
>> +#include <helper/odp_eth.h>
>> +#include <helper/odp_ip.h>
>> +
>> +#include <string.h>
>> +#include <stdio.h>
>> +
>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
>> odp_ipv4hdr_t *ipv4,
>> +                               size_t *offset_out);
>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
>> odp_ipv6hdr_t *ipv6,
>> +                               size_t *offset_out);
>> +
>> +void odp_packet_init(odp_packet_t pkt)
>> +{
>> +       odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
>> +       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>> buf_hdr);
>> +       uint8_t *start;
>> +       size_t len;
>> +
>> +       start = (uint8_t *)pkt_hdr + start_offset;
>> +       len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
>> +       memset(start, 0, len);
>> +
>> +       pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>> +       pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>> +       pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>> +}
>> +
>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf)
>> +{
>> +       return (odp_packet_t)buf;
>> +}
>> +
>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt)
>> +{
>> +       return (odp_buffer_t)pkt;
>> +}
>> +
>> +void odp_packet_set_len(odp_packet_t pkt, size_t len)
>> +{
>> +       /* for rte_pktmbuf */
>> +       odp_buffer_hdr_t *buf_hdr =
>> odp_buf_to_hdr(odp_buffer_from_packet(pkt));
>> +       buf_hdr->pkt.data_len = len;
>> +
>> +       odp_packet_hdr(pkt)->frame_len = len;
>> +}
>> +
>> +size_t odp_packet_get_len(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->frame_len;
>> +}
>> +
>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt)
>> +{
>> +       return odp_buffer_addr(odp_buffer_from_packet(pkt));
>> +}
>> +
>> +uint8_t *odp_packet_start(odp_packet_t pkt)
>> +{
>> +       return odp_packet_buf_addr(pkt) +
>> odp_packet_hdr(pkt)->frame_offset;
>> +}
>> +
>> +
>> +uint8_t *odp_packet_l2(odp_packet_t pkt)
>> +{
>> +       const size_t offset = odp_packet_l2_offset(pkt);
>> +
>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>> +               return NULL;
>> +
>> +       return odp_packet_buf_addr(pkt) + offset;
>> +}
>> +
>> +size_t odp_packet_l2_offset(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->l2_offset;
>> +}
>> +
>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset)
>> +{
>> +       odp_packet_hdr(pkt)->l2_offset = offset;
>> +}
>> +
>> +uint8_t *odp_packet_l3(odp_packet_t pkt)
>> +{
>> +       const size_t offset = odp_packet_l3_offset(pkt);
>> +
>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>> +               return NULL;
>> +
>> +       return odp_packet_buf_addr(pkt) + offset;
>> +}
>> +
>> +size_t odp_packet_l3_offset(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->l3_offset;
>> +}
>> +
>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset)
>> +{
>> +       odp_packet_hdr(pkt)->l3_offset = offset;
>> +}
>> +
>> +uint8_t *odp_packet_l4(odp_packet_t pkt)
>> +{
>> +       const size_t offset = odp_packet_l4_offset(pkt);
>> +
>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>> +               return NULL;
>> +
>> +       return odp_packet_buf_addr(pkt) + offset;
>> +}
>> +
>> +size_t odp_packet_l4_offset(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->l4_offset;
>> +}
>> +
>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset)
>> +{
>> +       odp_packet_hdr(pkt)->l4_offset = offset;
>> +}
>> +
>> +/**
>> + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP
>> + *
>> + * Internal function: caller is resposible for passing only valid packet
>> handles
>> + * , lengths and offsets (usually done&called in packet input).
>> + *
>> + * @param pkt        Packet handle
>> + * @param len        Packet length in bytes
>> + * @param frame_offset  Byte offset to L2 header
>> + */
>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset)
>> +{
>> +       odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
>> +       odp_ethhdr_t *eth;
>> +       odp_vlanhdr_t *vlan;
>> +       odp_ipv4hdr_t *ipv4;
>> +       odp_ipv6hdr_t *ipv6;
>> +       uint16_t ethtype;
>> +       size_t offset = 0;
>> +       uint8_t ip_proto = 0;
>> +
>> +       pkt_hdr->input_flags.eth = 1;
>> +       pkt_hdr->frame_offset = frame_offset;
>> +       pkt_hdr->frame_len = len;
>> +
>> +       if (odp_unlikely(len < ODP_ETH_LEN_MIN)) {
>> +               pkt_hdr->error_flags.frame_len = 1;
>> +               return;
>> +       } else if (len > ODP_ETH_LEN_MAX) {
>> +               pkt_hdr->input_flags.jumbo = 1;
>> +       }
>> +
>> +       /* Assume valid L2 header, no CRC/FCS check in SW */
>> +       pkt_hdr->input_flags.l2 = 1;
>> +       pkt_hdr->l2_offset = frame_offset;
>> +
>> +       eth = (odp_ethhdr_t *)odp_packet_start(pkt);
>> +       ethtype = odp_be_to_cpu_16(eth->type);
>> +       vlan = (odp_vlanhdr_t *)&eth->type;
>> +
>> +       if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
>> +               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->input_flags.vlan = 1;
>> +               ethtype = odp_be_to_cpu_16(vlan->tpid);
>> +               offset += sizeof(odp_vlanhdr_t);
>> +       }
>> +
>> +       /* Set l3_offset+flag only for known ethtypes */
>> +       switch (ethtype) {
>> +       case ODP_ETHTYPE_IPV4:
>> +               pkt_hdr->input_flags.ipv4 = 1;
>> +               pkt_hdr->input_flags.l3 = 1;
>> +               pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN +
>> offset;
>> +               ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
>> +               ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset);
>> +               break;
>> +       case ODP_ETHTYPE_IPV6:
>> +               pkt_hdr->input_flags.ipv6 = 1;
>> +               pkt_hdr->input_flags.l3 = 1;
>> +               pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN +
>> offset;
>> +               ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt);
>> +               ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset);
>> +               break;
>> +       case ODP_ETHTYPE_ARP:
>> +               pkt_hdr->input_flags.arp = 1;
>> +               /* fall through */
>> +       default:
>> +               ip_proto = 0;
>> +               break;
>> +       }
>> +
>> +       switch (ip_proto) {
>> +       case ODP_IPPROTO_UDP:
>> +               pkt_hdr->input_flags.udp = 1;
>> +               pkt_hdr->input_flags.l4 = 1;
>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>> +               break;
>> +       case ODP_IPPROTO_TCP:
>> +               pkt_hdr->input_flags.tcp = 1;
>> +               pkt_hdr->input_flags.l4 = 1;
>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>> +               break;
>> +       case ODP_IPPROTO_SCTP:
>> +               pkt_hdr->input_flags.sctp = 1;
>> +               pkt_hdr->input_flags.l4 = 1;
>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>> +               break;
>> +       case ODP_IPPROTO_ICMP:
>> +               pkt_hdr->input_flags.icmp = 1;
>> +               pkt_hdr->input_flags.l4 = 1;
>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>> +               break;
>> +       default:
>> +               /* 0 or unhandled IP protocols, don't set L4 flag+offset
>> */
>> +               if (pkt_hdr->input_flags.ipv6) {
>> +                       /* IPv6 next_hdr is not L4, mark as IP-option
>> instead */
>> +                       pkt_hdr->input_flags.ipopt = 1;
>> +               }
>> +               break;
>> +       }
>> +}
>> +
>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
>> odp_ipv4hdr_t *ipv4,
>> +                               size_t *offset_out)
>> +{
>> +       uint8_t ihl;
>> +       uint16_t frag_offset;
>> +
>> +       ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl);
>> +       if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) {
>> +               pkt_hdr->error_flags.ip_err = 1;
>> +               return 0;
>> +       }
>> +
>> +       if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) {
>> +               pkt_hdr->input_flags.ipopt = 1;
>> +               return 0;
>> +       }
>> +
>> +       /* A packet is a fragment if:
>> +       *  "more fragments" flag is set (all fragments except the last)
>> +       *     OR
>> +       *  "fragment offset" field is nonzero (all fragments except the
>> first)
>> +       */
>> +       frag_offset = odp_be_to_cpu_16(ipv4->frag_offset);
>> +       if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) {
>> +               pkt_hdr->input_flags.ipfrag = 1;
>> +               return 0;
>> +       }
>> +
>> +       if (ipv4->proto == ODP_IPPROTO_ESP ||
>> +           ipv4->proto == ODP_IPPROTO_AH) {
>> +               pkt_hdr->input_flags.ipsec = 1;
>> +               return 0;
>> +       }
>> +
>> +       /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after
>> return */
>> +
>> +       *offset_out = sizeof(uint32_t) * ihl;
>> +       return ipv4->proto;
>> +}
>> +
>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
>> odp_ipv6hdr_t *ipv6,
>> +                               size_t *offset_out)
>> +{
>> +       if (ipv6->next_hdr == ODP_IPPROTO_ESP ||
>> +           ipv6->next_hdr == ODP_IPPROTO_AH) {
>> +               pkt_hdr->input_flags.ipopt = 1;
>> +               pkt_hdr->input_flags.ipsec = 1;
>> +               return 0;
>> +       }
>> +
>> +       if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) {
>> +               pkt_hdr->input_flags.ipopt = 1;
>> +               pkt_hdr->input_flags.ipfrag = 1;
>> +               return 0;
>> +       }
>> +
>> +       /* Don't step through more extensions */
>> +       *offset_out = ODP_IPV6HDR_LEN;
>> +       return ipv6->next_hdr;
>> +}
>> +
>> +void odp_packet_print(odp_packet_t pkt)
>> +{
>> +       int max_len = 512;
>> +       char str[max_len];
>> +       int len = 0;
>> +       int n = max_len-1;
>> +       odp_packet_hdr_t *hdr = odp_packet_hdr(pkt);
>> +
>> +       len += snprintf(&str[len], n-len, "Packet ");
>> +       len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  input_flags  0x%x\n", hdr->input_flags.all);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  error_flags  0x%x\n", hdr->error_flags.all);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  output_flags 0x%x\n", hdr->output_flags.all);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  frame_offset %u\n", hdr->frame_offset);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  l2_offset    %u\n", hdr->l2_offset);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  l3_offset    %u\n", hdr->l3_offset);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  l4_offset    %u\n", hdr->l4_offset);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  frame_len    %u\n", hdr->frame_len);
>> +       len += snprintf(&str[len], n-len,
>> +                       "  input        %u\n", hdr->input);
>> +       str[len] = '\0';
>> +
>> +       printf("\n%s\n", str);
>> +}
>> +
>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src)
>> +{
>> +       odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst);
>> +       odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src);
>> +       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>> buf_hdr);
>> +       uint8_t *start_src;
>> +       uint8_t *start_dst;
>> +       size_t len;
>> +
>> +       if (pkt_dst == ODP_PACKET_INVALID || pkt_src ==
>> ODP_PACKET_INVALID)
>> +               return -1;
>> +
>> +       /* if (pkt_hdr_dst->buf_hdr.size < */
>> +       /*      pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */
>> +       if (pkt_hdr_dst->buf_hdr.buf_len <
>> +               pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset)
>> +               return -1;
>> +
>> +       /* Copy packet header */
>> +       start_dst = (uint8_t *)pkt_hdr_dst + start_offset;
>> +       start_src = (uint8_t *)pkt_hdr_src + start_offset;
>> +       len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
>> +       memcpy(start_dst, start_src, len);
>> +
>> +       /* Copy frame payload */
>> +       start_dst = (uint8_t *)odp_packet_start(pkt_dst);
>> +       start_src = (uint8_t *)odp_packet_start(pkt_src);
>> +       len = pkt_hdr_src->frame_len;
>> +       memcpy(start_dst, start_src, len);
>> +
>> +       /* Copy useful things from the buffer header */
>> +       /* pkt_hdr_dst->buf_hdr.cur_offset =
>> pkt_hdr_src->buf_hdr.cur_offset; */
>> +
>> +       /* Create a copy of the scatter list */
>> +       /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */
>> +       /*                      odp_buffer_from_packet(pkt_src)); */
>> +
>> +       return 0;
>> +}
>> diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c
>> b/platform/linux-dpdk/source/odp_packet_dpdk.c
>> new file mode 100644
>> index 0000000..6d16bbe
>> --- /dev/null
>> +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c
>> @@ -0,0 +1,177 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#define _GNU_SOURCE
>> +#include <stdio.h>
>> +#include <errno.h>
>> +#include <sys/types.h>
>> +#include <sys/stat.h>
>> +#include <sys/ioctl.h>
>> +#include <sys/mman.h>
>> +#include <poll.h>
>> +#include <unistd.h>
>> +#include <fcntl.h>
>> +#include <string.h>
>> +#include <stdlib.h>
>> +
>> +#include <linux/ethtool.h>
>> +#include <linux/sockios.h>
>> +
>> +#include <odp_hints.h>
>> +#include <odp_thread.h>
>> +
>> +#include <odp_packet_dpdk.h>
>> +#include <net/if.h>
>> +
>> +/*
>> + * RX and TX Prefetch, Host, and Write-back threshold values should be
>> + * carefully set for optimal performance. Consult the network
>> + * controller's datasheet and supporting DPDK documentation for guidance
>> + * on how these parameters should be set.
>> + */
>> +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
>> +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
>> +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg.
>> */
>> +
>> +/*
>> + * These default values are optimized for use with the Intel(R) 82599 10
>> GbE
>> + * Controller and the DPDK ixgbe PMD. Consider using other values for
>> other
>> + * network controllers and/or network drivers.
>> + */
>> +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg.
>> */
>> +#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
>> +#define TX_WTHRESH 0  /**< Default values of TX write-back threshold
>> reg. */
>> +
>> +#define MAX_PKT_BURST 32
>> +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
>> +#define RTE_TEST_RX_DESC_DEFAULT 128
>> +#define RTE_TEST_TX_DESC_DEFAULT 512
>> +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
>> +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
>> +
>> +static const struct rte_eth_conf port_conf = {
>> +       .rxmode = {
>> +               .split_hdr_size = 0,
>> +               .header_split   = 0, /**< Header Split disabled */
>> +               .hw_ip_checksum = 0, /**< IP checksum offload disabled */
>> +               .hw_vlan_filter = 0, /**< VLAN filtering disabled */
>> +               .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
>> +               .hw_strip_crc   = 0, /**< CRC stripped by hardware */
>> +       },
>> +       .txmode = {
>> +               .mq_mode = ETH_MQ_TX_NONE,
>> +       },
>> +};
>> +
>> +static const struct rte_eth_rxconf rx_conf = {
>> +       .rx_thresh = {
>> +               .pthresh = RX_PTHRESH,
>> +               .hthresh = RX_HTHRESH,
>> +               .wthresh = RX_WTHRESH,
>> +       },
>> +};
>> +
>> +static const struct rte_eth_txconf tx_conf = {
>> +       .tx_thresh = {
>> +               .pthresh = TX_PTHRESH,
>> +               .hthresh = TX_HTHRESH,
>> +               .wthresh = TX_WTHRESH,
>> +       },
>> +       .tx_free_thresh = 0, /* Use PMD default values */
>> +       .tx_rs_thresh = 0, /* Use PMD default values */
>> +       /*
>> +        * As the example won't handle mult-segments and offload cases,
>> +        * set the flag by default.
>> +        */
>> +       .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS,
>> +};
>> +
>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
>> +               odp_buffer_pool_t pool)
>> +{
>> +       ODP_DBG("setup_pkt_dpdk\n");
>> +
>> +       static struct ether_addr eth_addr[RTE_MAX_ETHPORTS];
>> +       uint8_t portid = 0;
>> +       uint16_t queueid = 0;
>> +       int ret;
>> +       printf("vincent netdev: %s\n", netdev);
>> +       printf("vincent pool: %lx\n", pool);
>> +
>> +       portid = atoi(netdev);
>> +       pkt_dpdk->portid = portid;
>> +       pkt_dpdk->queueid = queueid;
>> +       pkt_dpdk->pool = pool;
>> +       printf("vincent portid: %u\n", portid);
>> +
>> +       fflush(stdout);
>> +       ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
>> +       if (ret < 0)
>> +               ODP_ERR("Cannot configure device: err=%d, port=%u\n",
>> +                       ret, (unsigned) portid);
>> +
>> +       rte_eth_macaddr_get(portid, &eth_addr[portid]);
>> +       ODP_DBG("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
>> +               (unsigned) portid,
>> +               eth_addr[portid].addr_bytes[0],
>> +               eth_addr[portid].addr_bytes[1],
>> +               eth_addr[portid].addr_bytes[2],
>> +               eth_addr[portid].addr_bytes[3],
>> +               eth_addr[portid].addr_bytes[4],
>> +               eth_addr[portid].addr_bytes[5]);
>> +
>> +       /* init one RX queue on each port */
>> +       fflush(stdout);
>> +       ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
>> +                                    rte_eth_dev_socket_id(portid),
>> &rx_conf,
>> +                                    (struct rte_mempool *)pool);
>> +       if (ret < 0)
>> +               ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n",
>> +                       ret, (unsigned) portid);
>> +       ODP_DBG("dpdk rx queue setup done\n");
>> +
>> +       /* init one TX queue on each port */
>> +       fflush(stdout);
>> +       ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
>> +                       rte_eth_dev_socket_id(portid), &tx_conf);
>> +       if (ret < 0)
>> +               ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n",
>> +                       ret, (unsigned) portid);
>> +       ODP_DBG("dpdk tx queue setup done\n");
>> +
>> +       /* Start device */
>> +       ret = rte_eth_dev_start(portid);
>> +       if (ret < 0)
>> +               ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n",
>> +                       ret, (unsigned) portid);
>> +       ODP_DBG("dpdk setup done\n\n");
>> +
>> +
>> +       return 0;
>> +}
>> +
>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk)
>> +{
>> +       ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid);
>> +
>> +       return 0;
>> +}
>> +
>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
>> +               unsigned len)
>> +{
>> +       return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid,
>> +                               (uint16_t)pkt_dpdk->queueid,
>> +                               (struct rte_mbuf **)pkt_table,
>> (uint16_t)len);
>> +}
>> +
>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
>> +               unsigned len)
>> +{
>> +       return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid,
>> +                               (uint16_t)pkt_dpdk->queueid,
>> +                               (struct rte_mbuf **)pkt_table,
>> (uint16_t)len);
>> +}
>> diff --git a/platform/linux-dpdk/source/odp_packet_io.c
>> b/platform/linux-dpdk/source/odp_packet_io.c
>> new file mode 100644
>> index 0000000..abea0ec
>> --- /dev/null
>> +++ b/platform/linux-dpdk/source/odp_packet_io.c
>> @@ -0,0 +1,561 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_packet_io.h>
>> +#include <odp_packet_io_internal.h>
>> +#include <odp_packet_io_queue.h>
>> +#include <odp_packet.h>
>> +#include <odp_packet_internal.h>
>> +#include <odp_internal.h>
>> +#include <odp_spinlock.h>
>> +#include <odp_shared_memory.h>
>> +#include <odp_packet_socket.h>
>> +#ifdef ODP_HAVE_NETMAP
>> +#include <odp_packet_netmap.h>
>> +#endif
>> +#include <odp_hints.h>
>> +#include <odp_config.h>
>> +#include <odp_queue_internal.h>
>> +#include <odp_schedule_internal.h>
>> +#include <odp_debug.h>
>> +
>> +#include <odp_pktio_socket.h>
>> +#ifdef ODP_HAVE_NETMAP
>> +#include <odp_pktio_netmap.h>
>> +#endif
>> +
>> +#include <string.h>
>> +
>> +typedef struct {
>> +       pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
>> +} pktio_table_t;
>> +
>> +static pktio_table_t *pktio_tbl;
>> +
>> +
>> +static pktio_entry_t *get_entry(odp_pktio_t id)
>> +{
>> +       if (odp_unlikely(id == ODP_PKTIO_INVALID ||
>> +                        id > ODP_CONFIG_PKTIO_ENTRIES))
>> +               return NULL;
>> +
>> +       return &pktio_tbl->entries[id - 1];
>> +}
>> +
>> +int odp_pktio_init_global(void)
>> +{
>> +       char name[ODP_QUEUE_NAME_LEN];
>> +       pktio_entry_t *pktio_entry;
>> +       queue_entry_t *queue_entry;
>> +       odp_queue_t qid;
>> +       int id;
>> +
>> +       pktio_tbl = odp_shm_reserve("odp_pktio_entries",
>> +                                   sizeof(pktio_table_t),
>> +                                   sizeof(pktio_entry_t));
>> +       if (pktio_tbl == NULL)
>> +               return -1;
>> +
>> +       memset(pktio_tbl, 0, sizeof(pktio_table_t));
>> +
>> +       for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
>> +               pktio_entry = get_entry(id);
>> +
>> +               odp_spinlock_init(&pktio_entry->s.lock);
>> +
>> +               /* Create a default output queue for each pktio resource
>> */
>> +               snprintf(name, sizeof(name), "%i-pktio_outq_default",
>> (int)id);
>> +               name[ODP_QUEUE_NAME_LEN-1] = '\0';
>> +
>> +               qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, NULL);
>> +               if (qid == ODP_QUEUE_INVALID)
>> +                       return -1;
>> +               pktio_entry->s.outq_default = qid;
>> +
>> +               queue_entry = queue_to_qentry(qid);
>> +               queue_entry->s.pktout = id;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +int odp_pktio_init_local(void)
>> +{
>> +       return 0;
>> +}
>> +
>> +static int is_free(pktio_entry_t *entry)
>> +{
>> +       return (entry->s.taken == 0);
>> +}
>> +
>> +static void set_free(pktio_entry_t *entry)
>> +{
>> +       entry->s.taken = 0;
>> +}
>> +
>> +static void set_taken(pktio_entry_t *entry)
>> +{
>> +       entry->s.taken = 1;
>> +}
>> +
>> +static void lock_entry(pktio_entry_t *entry)
>> +{
>> +       odp_spinlock_lock(&entry->s.lock);
>> +}
>> +
>> +static void unlock_entry(pktio_entry_t *entry)
>> +{
>> +       odp_spinlock_unlock(&entry->s.lock);
>> +}
>> +
>> +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t
>> *params)
>> +{
>> +       set_taken(entry);
>> +       entry->s.inq_default = ODP_QUEUE_INVALID;
>> +       switch (params->type) {
>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>> +               memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock));
>> +               memset(&entry->s.pkt_sock_mmap, 0,
>> +                      sizeof(entry->s.pkt_sock_mmap));
>> +               break;
>> +#ifdef ODP_HAVE_NETMAP
>> +       case ODP_PKTIO_TYPE_NETMAP:
>> +               memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm));
>> +               break;
>> +#endif
>> +       case ODP_PKTIO_TYPE_DPDK:
>> +               memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk));
>> +               break;
>> +       default:
>> +               ODP_ERR("Packet I/O type not supported. Please
>> recompile\n");
>> +               break;
>> +       }
>> +       /* Save pktio parameters, type is the most useful */
>> +       memcpy(&entry->s.params, params, sizeof(*params));
>> +}
>> +
>> +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
>> +{
>> +       odp_pktio_t id;
>> +       pktio_entry_t *entry;
>> +       int i;
>> +
>> +       for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
>> +               entry = &pktio_tbl->entries[i];
>> +               if (is_free(entry)) {
>> +                       lock_entry(entry);
>> +                       if (is_free(entry)) {
>> +                               init_pktio_entry(entry, params);
>> +                               id = i + 1;
>> +                               return id; /* return with entry locked! */
>> +                       }
>> +                       unlock_entry(entry);
>> +               }
>> +       }
>> +
>> +       return ODP_PKTIO_INVALID;
>> +}
>> +
>> +static int free_pktio_entry(odp_pktio_t id)
>> +{
>> +       pktio_entry_t *entry = get_entry(id);
>> +
>> +       if (entry == NULL)
>> +               return -1;
>> +
>> +       set_free(entry);
>> +
>> +       return 0;
>> +}
>> +
>> +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
>> +                          odp_pktio_params_t *params)
>> +{
>> +       odp_pktio_t id;
>> +       pktio_entry_t *pktio_entry;
>> +       int res;
>> +
>> +       if (params == NULL) {
>> +               ODP_ERR("Invalid pktio params\n");
>> +               return ODP_PKTIO_INVALID;
>> +       }
>> +
>> +       switch (params->type) {
>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>> +               ODP_DBG("Allocating socket pktio\n");
>> +               break;
>> +#ifdef ODP_HAVE_NETMAP
>> +       case ODP_PKTIO_TYPE_NETMAP:
>> +               ODP_DBG("Allocating netmap pktio\n");
>> +               break;
>> +#endif
>> +       case ODP_PKTIO_TYPE_DPDK:
>> +               ODP_DBG("Allocating dpdk pktio\n");
>> +               break;
>> +       default:
>> +               ODP_ERR("Invalid pktio type: %02x\n", params->type);
>> +               return ODP_PKTIO_INVALID;
>> +       }
>> +
>> +       id = alloc_lock_pktio_entry(params);
>> +       if (id == ODP_PKTIO_INVALID) {
>> +               ODP_ERR("No resources available.\n");
>> +               return ODP_PKTIO_INVALID;
>> +       }
>> +       /* if successful, alloc_pktio_entry() returns with the entry
>> locked */
>> +
>> +       pktio_entry = get_entry(id);
>> +
>> +       switch (params->type) {
>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>> +               res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, pool);
>> +               if (res == -1) {
>> +                       close_pkt_sock(&pktio_entry->s.pkt_sock);
>> +                       free_pktio_entry(id);
>> +                       id = ODP_PKTIO_INVALID;
>> +               }
>> +               break;
>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>> +               res = setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>> dev,
>> +                               pool, params->sock_params.fanout);
>> +               if (res == -1) {
>> +
>> close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap);
>> +                       free_pktio_entry(id);
>> +                       id = ODP_PKTIO_INVALID;
>> +               }
>> +               break;
>> +#ifdef ODP_HAVE_NETMAP
>> +       case ODP_PKTIO_TYPE_NETMAP:
>> +
>> +               res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev,
>> +                               pool, &params->nm_params);
>> +               if (res == -1) {
>> +                       close_pkt_netmap(&pktio_entry->s.pkt_nm);
>> +                       free_pktio_entry(id);
>> +                       id = ODP_PKTIO_INVALID;
>> +               }
>> +               break;
>> +#endif
>> +       case ODP_PKTIO_TYPE_DPDK:
>> +               res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, pool);
>> +               if (res == -1) {
>> +                       close_pkt_dpdk(&pktio_entry->s.pkt_dpdk);
>> +                       free_pktio_entry(id);
>> +                       id = ODP_PKTIO_INVALID;
>> +               }
>> +               break;
>> +       default:
>> +               free_pktio_entry(id);
>> +               id = ODP_PKTIO_INVALID;
>> +               ODP_ERR("Invalid pktio type. Please recompile.\n");
>> +               break;
>> +       }
>> +
>> +       unlock_entry(pktio_entry);
>> +       return id;
>> +}
>> +
>> +int odp_pktio_close(odp_pktio_t id)
>> +{
>> +       pktio_entry_t *entry;
>> +       int res = -1;
>> +
>> +       entry = get_entry(id);
>> +       if (entry == NULL)
>> +               return -1;
>> +
>> +       lock_entry(entry);
>> +       if (!is_free(entry)) {
>> +               switch (entry->s.params.type) {
>> +               case ODP_PKTIO_TYPE_SOCKET_BASIC:
>> +               case ODP_PKTIO_TYPE_SOCKET_MMSG:
>> +                       res  = close_pkt_sock(&entry->s.pkt_sock);
>> +                       break;
>> +               case ODP_PKTIO_TYPE_SOCKET_MMAP:
>> +                       res  =
>> close_pkt_sock_mmap(&entry->s.pkt_sock_mmap);
>> +                       break;
>> +#ifdef ODP_HAVE_NETMAP
>> +               case ODP_PKTIO_TYPE_NETMAP:
>> +                       res  = close_pkt_netmap(&entry->s.pkt_nm);
>> +                       break;
>> +#endif
>> +               case ODP_PKTIO_TYPE_DPDK:
>> +                       res  = close_pkt_dpdk(&entry->s.pkt_dpdk);
>> +                       break;
>> +               default:
>> +                       break;
>> +               res |= free_pktio_entry(id);
>> +               }
>> +       }
>> +       unlock_entry(entry);
>> +
>> +       if (res != 0)
>> +               return -1;
>> +
>> +       return 0;
>> +}
>> +
>> +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio)
>> +{
>> +       odp_packet_hdr(pkt)->input = pktio;
>> +}
>> +
>> +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt)
>> +{
>> +       return odp_packet_hdr(pkt)->input;
>> +}
>> +
>> +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned
>> len)
>> +{
>> +       pktio_entry_t *pktio_entry = get_entry(id);
>> +       int pkts;
>> +       int i;
>> +
>> +       if (pktio_entry == NULL)
>> +               return -1;
>> +
>> +       lock_entry(pktio_entry);
>> +       switch (pktio_entry->s.params.type) {
>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>> +               pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock,
>> +                               pkt_table, len);
>> +               break;
>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>> +               pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
>> +                               pkt_table, len);
>> +               break;
>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>> +               pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>> +                               pkt_table, len);
>> +               break;
>> +#ifdef ODP_HAVE_NETMAP
>> +       case ODP_PKTIO_TYPE_NETMAP:
>> +               pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm, pkt_table,
>> len);
>> +               break;
>> +#endif
>> +       case ODP_PKTIO_TYPE_DPDK:
>> +               pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table,
>> len);
>> +               break;
>> +       default:
>> +               pkts = -1;
>> +               break;
>> +       }
>> +
>> +       unlock_entry(pktio_entry);
>> +       if (pkts < 0)
>> +               return pkts;
>> +
>> +       for (i = 0; i < pkts; ++i)
>> +               odp_pktio_set_input(pkt_table[i], id);
>> +
>> +       return pkts;
>> +}
>> +
>> +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned
>> len)
>> +{
>> +       pktio_entry_t *pktio_entry = get_entry(id);
>> +       int pkts;
>> +
>> +       if (pktio_entry == NULL)
>> +               return -1;
>> +
>> +       lock_entry(pktio_entry);
>> +       switch (pktio_entry->s.params.type) {
>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>> +               pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock,
>> +                               pkt_table, len);
>> +               break;
>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>> +               pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
>> +                               pkt_table, len);
>> +               break;
>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>> +               pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>> +                               pkt_table, len);
>> +               break;
>> +#ifdef ODP_HAVE_NETMAP
>> +       case ODP_PKTIO_TYPE_NETMAP:
>> +               pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm,
>> +                               pkt_table, len);
>> +               break;
>> +#endif
>> +       case ODP_PKTIO_TYPE_DPDK:
>> +               pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk,
>> +                               pkt_table, len);
>> +               break;
>> +       default:
>> +               pkts = -1;
>> +       }
>> +       unlock_entry(pktio_entry);
>> +
>> +       return pkts;
>> +}
>> +
>> +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue)
>> +{
>> +       pktio_entry_t *pktio_entry = get_entry(id);
>> +       queue_entry_t *qentry = queue_to_qentry(queue);
>> +
>> +       if (pktio_entry == NULL || qentry == NULL)
>> +               return -1;
>> +
>> +       if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN)
>> +               return -1;
>> +
>> +       lock_entry(pktio_entry);
>> +       pktio_entry->s.inq_default = queue;
>> +       unlock_entry(pktio_entry);
>> +
>> +       queue_lock(qentry);
>> +       qentry->s.pktin = id;
>> +       qentry->s.status = QUEUE_STATUS_SCHED;
>> +       queue_unlock(qentry);
>> +
>> +       odp_schedule_queue(queue, qentry->s.param.sched.prio);
>> +
>> +       return 0;
>> +}
>> +
>> +int odp_pktio_inq_remdef(odp_pktio_t id)
>> +{
>> +       return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID);
>> +}
>> +
>> +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
>> +{
>> +       pktio_entry_t *pktio_entry = get_entry(id);
>> +
>> +       if (pktio_entry == NULL)
>> +               return ODP_QUEUE_INVALID;
>> +
>> +       return pktio_entry->s.inq_default;
>> +}
>> +
>> +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
>> +{
>> +       pktio_entry_t *pktio_entry = get_entry(id);
>> +
>> +       if (pktio_entry == NULL)
>> +               return ODP_QUEUE_INVALID;
>> +
>> +       return pktio_entry->s.outq_default;
>> +}
>> +
>> +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
>> +{
>> +       odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t) buf_hdr);
>> +       int len = 1;
>> +       int nbr;
>> +
>> +       nbr = odp_pktio_send(qentry->s.pktout, &pkt, len);
>> +       return (nbr == len ? 0 : -1);
>> +}
>> +
>> +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry)
>> +{
>> +       (void)qentry;
>> +       return NULL;
>> +}
>> +
>> +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
>> +                    int num)
>> +{
>> +       odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>> +       int nbr;
>> +       int i;
>> +
>> +       for (i = 0; i < num; ++i)
>> +               pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t)
>> buf_hdr[i]);
>> +
>> +       nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num);
>> +       return (nbr == num ? 0 : -1);
>> +}
>> +
>> +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
>> +                    int num)
>> +{
>> +       (void)qentry;
>> +       (void)buf_hdr;
>> +       (void)num;
>> +
>> +       return 0;
>> +}
>> +
>> +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
>> +{
>> +       /* Use default action */
>> +       return queue_enq(qentry, buf_hdr);
>> +}
>> +
>> +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
>> +{
>> +       odp_buffer_hdr_t *buf_hdr;
>> +
>> +       buf_hdr = queue_deq(qentry);
>> +
>> +       if (buf_hdr == NULL) {
>> +               odp_packet_t pkt;
>> +               odp_buffer_t buf;
>> +               odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>> +               odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
>> +               int pkts, i, j;
>> +
>> +               pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
>> +                                     QUEUE_MULTI_MAX);
>> +
>> +               if (pkts > 0) {
>> +                       pkt = pkt_tbl[0];
>> +                       buf = odp_buffer_from_packet(pkt);
>> +                       buf_hdr = odp_buf_to_hdr(buf);
>> +
>> +                       for (i = 1, j = 0; i < pkts; ++i) {
>> +                               buf = odp_buffer_from_packet(pkt_tbl[i]);
>> +                               tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf);
>> +                       }
>> +                       queue_enq_multi(qentry, tmp_hdr_tbl, j);
>> +               }
>> +       }
>> +
>> +       return buf_hdr;
>> +}
>> +
>> +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
>> int num)
>> +{
>> +       /* Use default action */
>> +       return queue_enq_multi(qentry, buf_hdr, num);
>> +}
>> +
>> +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
>> int num)
>> +{
>> +       int nbr;
>> +
>> +       nbr = queue_deq_multi(qentry, buf_hdr, num);
>> +
>> +       if (nbr < num) {
>> +               odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>> +               odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
>> +               odp_buffer_t buf;
>> +               int pkts, i;
>> +
>> +               pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
>> +                                     QUEUE_MULTI_MAX);
>> +               if (pkts > 0) {
>> +                       for (i = 0; i < pkts; ++i) {
>> +                               buf = odp_buffer_from_packet(pkt_tbl[i]);
>> +                               tmp_hdr_tbl[i] = odp_buf_to_hdr(buf);
>> +                       }
>> +                       queue_enq_multi(qentry, tmp_hdr_tbl, pkts);
>> +               }
>> +       }
>> +
>> +       return nbr;
>> +}
>> diff --git a/platform/linux-dpdk/source/odp_queue.c
>> b/platform/linux-dpdk/source/odp_queue.c
>> new file mode 100644
>> index 0000000..554b8ea
>> --- /dev/null
>> +++ b/platform/linux-dpdk/source/odp_queue.c
>> @@ -0,0 +1,435 @@
>> +/* Copyright (c) 2013, Linaro Limited
>> + * All rights reserved.
>> + *
>> + * SPDX-License-Identifier:     BSD-3-Clause
>> + */
>> +
>> +#include <odp_queue.h>
>> +#include <odp_queue_internal.h>
>> +#include <odp_std_types.h>
>> +#include <odp_align.h>
>> +#include <odp_buffer.h>
>> +#include <odp_buffer_internal.h>
>> +#include <odp_buffer_pool_internal.h>
>> +#include <odp_internal.h>
>> +#include <odp_shared_memory.h>
>> +#include <odp_schedule_internal.h>
>> +#include <odp_config.h>
>> +#include <odp_packet_io_internal.h>
>> +#include <odp_packet_io_queue.h>
>> +#include <odp_debug.h>
>> +#include <odp_hints.h>
>> +
>> +#ifdef USE_TICKETLOCK
>> +#include <odp_ticketlock.h>
>> +#define LOCK(a)      odp_ticketlock_lock(a)
>> +#define UNLOCK(a)    odp_ticketlock_unlock(a)
>> +#define LOCK_INIT(a) odp_ticketlock_init(a)
>> +#else
>> +#include <odp_spinlock.h>
>> +#define LOCK(a)      odp_spinlock_lock(a)
>> +#define UNLOCK(a)    odp_spinlock_unlock(a)
>> +#define LOCK_INIT(a) odp_spinlock_init(a)
>> +#endif
>> +
>> +#include <string.h>
>> +
>> +
>> +typedef struct queue_table_t {
>> +       queue_entry_t  queue[ODP_CONFIG_QUEUES];
>> +} queue_table_t;
>> +
>> +static queue_table_t *queue_tbl;
>> +
>> +
>> +queue_entry_t *get_qentry(uint32_t queue_id)
>> +{
>> +       return &queue_tbl->queue[queue_id];
>> +}
>> +
>> +static void queue_init(queue_entry_t *queue, const char *name,
>> +                      odp_queue_type_t type, odp_queue_param_t *param)
>> +{
>> +       strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1);
>> +       queue->s.type = type;
>> +
>> +       if (param) {
>> +               memcpy(&queue->s.param, param, sizeof(odp_queue_param_t));
>> +       } else {
>> +               /* Defaults */
>> +               memset(&queue->s.param, 0, sizeof(odp_queue_param_t));
>> +               queue->s.param.sched.prio  = ODP_SCHED_PRIO_DEFAULT;
>> +               queue->s.param.sched.sync  = ODP_SCHED_SYNC_DEFAULT;
>> +               queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT;
>> +       }
>> +
>> +       switch (type) {
>> +       case ODP_QUEUE_TYPE_PKTIN:
>> +               queue->s.enqueue = pktin_enqueue;
>> +               queue->s.dequeue = pktin_dequeue;
>> +               queue->s.enqueue_multi = pktin_enq_multi;
>> +               queue->s.dequeue_multi = pktin_deq_multi;
>> +               break;
>> +       case ODP_QUEUE_TYPE_PKTOUT:
>> +               queue->s.enqueue = pktout_enqueue;
>> +               queue->s.dequeue = pktout_dequeue;
>> +               queue->s.enqueue_multi = pktout_enq_multi;
>> +               queue->s.dequeue_multi = pktout_deq_multi;
>> +               break;
>> +       default:
>> +               queue->s.enqueue = queue_enq;
>> +               queue->s.dequeue = queue_deq;
>> +               queue->s.enqueue_multi = queue_enq_multi;
>> +               queue->s.dequeue_multi = queue_deq_multi;
>> +               break;
>> +       }
>> +
>> +       queue->s.head = NULL;
>> +       queue->s.tail = NULL;
>> +       queue->s.sched_buf = ODP_BUFFER_INVALID;
>> +}
>> +
>> +
>> +int odp_queue_init_global(void)
>> +{
>> +       uint32_t i;
>> +
>> +       ODP_DBG("Queue init ... ");
>> +
>> +       queue_tbl = odp_shm_reserve("odp_queues",
>> +                                   sizeof(queue_table_t),
>> +                                   sizeof(queue_entry_t));
>> +
>> +       if (queue_tbl == NULL)
>> +               return -1;
>> +
>> +       memset(queue_tbl, 0, sizeof(queue_table_t));
>> +
>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>> +               /* init locks */
>> +               queue_entry_t *queue = get_qentry(i);
>> +               LOCK_INIT(&queue->s.lock);
>> +               queue->s.handle = queue_from_id(i);
>> +       }
>> +
>> +       ODP_DBG("done\n");
>> +       ODP_DBG("Queue init global\n");
>> +       ODP_DBG("  struct queue_entry_s size %zu\n",
>> +               sizeof(struct queue_entry_s));
>> +       ODP_DBG("  queue_entry_t size        %zu\n",
>> +               sizeof(queue_entry_t));
>> +       ODP_DBG("\n");
>> +
>> +       return 0;
>> +}
>> +
>> +odp_queue_type_t odp_queue_type(odp_queue_t handle)
>> +{
>> +       queue_entry_t *queue;
>> +
>> +       queue = queue_to_qentry(handle);
>> +
>> +       return queue->s.type;
>> +}
>> +
>> +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle)
>> +{
>> +       queue_entry_t *queue;
>> +
>> +       queue = queue_to_qentry(handle);
>> +
>> +       return queue->s.param.sched.sync;
>> +}
>> +
>> +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
>> +                            odp_queue_param_t *param)
>> +{
>> +       uint32_t i;
>> +       queue_entry_t *queue;
>> +       odp_queue_t handle = ODP_QUEUE_INVALID;
>> +
>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>> +               queue = &queue_tbl->queue[i];
>> +
>> +               if (queue->s.status != QUEUE_STATUS_FREE)
>> +                       continue;
>> +
>> +               LOCK(&queue->s.lock);
>> +               if (queue->s.status == QUEUE_STATUS_FREE) {
>> +                       queue_init(queue, name, type, param);
>> +
>> +                       if (type == ODP_QUEUE_TYPE_SCHED ||
>> +                           type == ODP_QUEUE_TYPE_PKTIN)
>> +                               queue->s.status = QUEUE_STATUS_NOTSCHED;
>> +                       else
>> +                               queue->s.status = QUEUE_STATUS_READY;
>> +
>> +                       handle = queue->s.handle;
>> +                       UNLOCK(&queue->s.lock);
>> +                       break;
>> +               }
>> +               UNLOCK(&queue->s.lock);
>> +       }
>> +
>> +       if (handle != ODP_QUEUE_INVALID &&
>> +           (type == ODP_QUEUE_TYPE_SCHED || type ==
>> ODP_QUEUE_TYPE_PKTIN)) {
>> +               odp_buffer_t buf;
>> +
>> +               buf = odp_schedule_buffer_alloc(handle);
>> +               if (buf == ODP_BUFFER_INVALID) {
>> +                       ODP_ERR("queue_init: sched buf alloc failed\n");
>> +                       return ODP_QUEUE_INVALID;
>> +               }
>> +
>> +               queue->s.sched_buf = buf;
>> +               odp_schedule_mask_set(handle, queue->s.param.sched.prio);
>> +       }
>> +
>> +       return handle;
>> +}
>> +
>> +
>> +odp_buffer_t queue_sched_buf(odp_queue_t handle)
>> +{
>> +       queue_entry_t *queue;
>> +       queue = queue_to_qentry(handle);
>> +
>> +       return queue->s.sched_buf;
>> +}
>> +
>> +
>> +int queue_sched_atomic(odp_queue_t handle)
>> +{
>> +       queue_entry_t *queue;
>> +       queue = queue_to_qentry(handle);
>> +
>> +       return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC;
>> +}
>> +
>> +
>> +odp_queue_t odp_queue_lookup(const char *name)
>> +{
>> +       uint32_t i;
>> +
>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>> +               queue_entry_t *queue = &queue_tbl->queue[i];
>> +
>> +               if (queue->s.status == QUEUE_STATUS_FREE)
>> +                       continue;
>> +
>> +               LOCK(&queue->s.lock);
>> +               if (strcmp(name, queue->s.name) == 0) {
>> +                       /* found it */
>> +                       UNLOCK(&queue->s.lock);
>> +                       return queue->s.handle;
>> +               }
>> +               UNLOCK(&queue->s.lock);
>> +       }
>> +
>> +       return ODP_QUEUE_INVALID;
>> +}
>> +
>> +
>> +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
>> +{
>> +       int sched = 0;
>> +
>> +       LOCK(&queue->s.lock);
>> +       if (queue->s.head == NULL) {
>> +               /* Empty queue */
>> +               queue->s.head = buf_hdr;
>> +               queue->s.tail = buf_hdr;
>> +               buf_hdr->pkt.next = NULL;
>> +       } else {
>> +               queue->s.tail->pkt.next = buf_hdr;
>> +               queue->s.tail = buf_hdr;
>> +               buf_hdr->pkt.next = NULL;
>> +       }
>> +
>> +       if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
>> +               queue->s.status = QUEUE_STATUS_SCHED;
>> +               sched = 1; /* retval: schedule queue */
>> +       }
>> +       UNLOCK(&queue->s.lock);
>> +
>> +       /* Add queue to scheduling */
>> +       if (sched == 1)
>> +               odp_schedule_queue(queue->s.handle,
>> queue->s.param.sched.prio);
>> +
>> +       return 0;
>> +}
>> +
>> +
>> +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
>> int num)
>> +{
>> +       int sched = 0;
>> +       int i;
>> +       odp_buffer_hdr_t *tail;
>> +
>> +       for (i = 0; i < num - 1; i++)
>> +               buf_hdr[i]->pkt.next = buf_hdr[i+1];
>> +
>> +       tail = buf_hdr[num-1];
>> +       buf_hdr[num-1]->pkt.next = NULL;
>> +
>> +       LOCK(&queue->s.lock);
>> +       /* Empty queue */
>> +       if (queue->s.head == NULL)
>> +               queue->s.head = buf_hdr[0];
>> +       else
>> +               queue->s.tail->pkt.next = buf_hdr[0];
>> +
>> +       queue->s.tail = tail;
>> +
>> +       if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
>> +               queue->s.status = QUEUE_STATUS_SCHED;
>> +               sched = 1; /* retval: schedule queue */
>> +       }
>> +       UNLOCK(&queue->s.lock);
>> +
>> +       /* Add queue to scheduling */
>> +       if (sched == 1)
>> +               odp_schedule_queue(queue->s.handle,
>> queue->s.param.sched.prio);
>> +
>> +       return 0;
>> +}
>> +
>> +
>> +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int num)
>> +{
>> +       odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
>> +       queue_entry_t *queue;
>> +       int i;
>> +
>> +       if (num > QUEUE_MULTI_MAX)
>> +               num = QUEUE_MULTI_MAX;
>> +
>> +       queue = queue_to_qentry(handle);
>> +
>> +       for (i = 0; i < num; i++)
>> +               buf_hdr[i] = odp_buf_to_hdr(buf[i]);
>> +
>> +       return queue->s.enqueue_multi(queue, buf_hdr, num);
>> +}
>> +
>> +
>> +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf)
>> +{
>> +       odp_buffer_hdr_t *buf_hdr;
>> +       queue_entry_t *queue;
>> +
>> +       queue   = queue_to_qentry(handle);
>> +       buf_hdr = odp_buf_to_hdr(buf);
>> +
>> +       return queue->s.enqueue(queue, buf_hdr);
>> +}
>> +
>> +
>> +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
>> +{
>> +       odp_buffer_hdr_t *buf_hdr = NULL;
>> +
>> +       LOCK(&queue->s.lock);
>> +
>> +       if (queue->s.head == NULL) {
>> +               /* Already empty queue */
>> +               if (queue->s.status == QUEUE_STATUS_SCHED &&
>> +                   queue->s.type != ODP_QUEUE_TYPE_PKTIN)
>> +                       queue->s.status = QUEUE_STATUS_NOTSCHED;
>> +       } else {
>> +               buf_hdr       = queue->s.head;
>> +               queue->s.head = buf_hdr->pkt.next;
>> +               buf_hdr->pkt.next = NULL;
>> +
>> +               if (queue->s.head == NULL) {
>> +                       /* Queue is now empty */
>> +                       queue->s.tail = NULL;
>> +               }
>> +       }
>> +
>> +       UNLOCK(&queue->s.lock);
>> +
>> +       return buf_hdr;
>> +}
>> +
>> +
>> +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
>> int num)
>> +{
>> +       int i = 0;
>> +
>> +       LOCK(&queue->s.lock);
>> +
>> +       if (queue->s.head == NULL) {
>> +               /* Already empty queue */
>> +               if (queue->s.status == QUEUE_STATUS_SCHED &&
>> +                   queue->s.type != ODP_QUEUE_TYPE_PKTIN)
>> +                       queue->s.status = QUEUE_STATUS_NOTSCHED;
>> +       } else {
>> +               odp_buffer_hdr_t *hdr = queue->s.head;
>> +
>> +               for (; i < num && hdr; i++) {
>> +                       buf_hdr[i]       = hdr;
>> +                       /* odp_prefetch(hdr->addr); */
>> +                       hdr              = hdr->pkt.next;
>> +                       buf_hdr[i]->pkt.next = NULL;
>> +               }
>> +
>> +               queue->s.head = hdr;
>> +
>> +               if (hdr == NULL) {
>> +                       /* Queue is now empty */
>> +                       queue->s.tail = NULL;
>> +               }
>> +       }
>> +
>> +       UNLOCK(&queue->s.lock);
>> +
>> +       return i;
>> +}
>> +
>> +
>> +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int num)
>> +{
>> +       queue_entry_t *queue;
>> +       odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
>> +       int i, ret;
>> +
>> +       if (num > QUEUE_MULTI_MAX)
>> +               num = QUEUE_MULTI_MAX;
>> +
>> +       queue = queue_to_qentry(handle);
>> +
>> +       ret = queue->s.dequeue_multi(queue, buf_hdr, num);
>> +
>> +       for (i = 0; i < ret; i++)
>> +               buf[i] = (odp_buffer_t) buf_hdr[i];
>> +
>> +       return ret;
>> +}
>> +
>> +
>> +odp_buffer_t odp_queue_deq(odp_queue_t handle)
>> +{
>> +       queue_entry_t *queue;
>> +       odp_buffer_hdr_t *buf_hdr;
>> +
>> +       queue   = queue_to_qentry(handle);
>> +       buf_hdr = queue->s.dequeue(queue);
>> +
>> +       if (buf_hdr)
>> +               return (odp_buffer_t) buf_hdr;
>> +
>> +       return ODP_BUFFER_INVALID;
>> +}
>> +
>> +
>> +void queue_lock(queue_entry_t *queue)
>> +{
>> +       LOCK(&queue->s.lock);
>> +}
>> +
>> +
>> +void queue_unlock(queue_entry_t *queue)
>> +{
>> +       UNLOCK(&queue->s.lock);
>> +}
>> --
>> 1.9.1
>>
>>
>> _______________________________________________
>> lng-odp mailing list
>> lng-odp@lists.linaro.org
>> http://lists.linaro.org/mailman/listinfo/lng-odp
>>
>
>
>
> --
> *Mike Holmes*
> Linaro Technical Manager / Lead
> LNG - ODP
>
Mike Holmes July 12, 2014, 12:01 p.m. UTC | #3
On 12 July 2014 04:20, Venkatesh Vivekanandan <
venkatesh.vivekanandan@linaro.org> wrote:

>
>
>
> On 12 July 2014 01:14, Mike Holmes <mike.holmes@linaro.org> wrote:
>
>> Adds whitespace errors when applied.
>>
>
> Ran checkpatch.pl before submitting the patch. Please point to the
> error/warning if any.
>
mike@fedora1:~/git/odp$ git am
~/incoming/lng-odp_PATCH_1-2_initial_odp_dpdk.mbox
Applying: initial odp dpdk
error: platform/linux-dpdk/Makefile: already exists in working directory
/home/mike/git/odp/.git/rebase-apply/patch:216: new blank line at EOF.
+
/home/mike/git/odp/.git/rebase-apply/patch:792: new blank line at EOF.
+
/home/mike/git/odp/.git/rebase-apply/patch:988: new blank line at EOF.
+
/home/mike/git/odp/.git/rebase-apply/patch:1134: new blank line at EOF.
+
/home/mike/git/odp/.git/rebase-apply/patch:1192: new blank line at EOF.
+
Patch failed at 0001 initial odp dpdk
The copy of the patch that failed is found in:
   /home/mike/git/odp/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".


>
>
>> Also needs a README like the one in linux-keystone to indicate such
>> things as setting ./configure --with-platform=linux-dpdk
>> And how to then ensure  dpdk is installed to resolve things like
>>
>
> Forgot to mention that prerequisite is, dpdk should be checked out and
> compiled. I will probably add it in a README and send out a patch for that.
>
>
>> /usr/include/stdc-predef.h:59:1: fatal error:
>> ../../../dpdk/build/include/rte_config.h: No such file or directory
>>
>
>>
>> On 11 July 2014 14:35, <venkatesh.vivekanandan@linaro.org> wrote:
>>
>>> From: Vincent Hsu <vincent.hsu@linaro.org>
>>>
>>> Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org
>>> >
>>> ---
>>>  platform/linux-dpdk/Makefile                       | 158 ++++++
>>>  platform/linux-dpdk/Makefile.inc                   |   7 +
>>>  platform/linux-dpdk/include/api/odp_buffer.h       | 101 ++++
>>>  platform/linux-dpdk/include/api/odp_buffer_pool.h  |  99 ++++
>>>  platform/linux-dpdk/include/api/odp_packet.h       | 228 +++++++++
>>>  platform/linux-dpdk/include/api/odp_pktio_types.h  |  45 ++
>>>  platform/linux-dpdk/include/odp_buffer_internal.h  |  79 +++
>>>  .../linux-dpdk/include/odp_buffer_pool_internal.h  |  90 ++++
>>>  platform/linux-dpdk/include/odp_packet_dpdk.h      |  88 ++++
>>>  platform/linux-dpdk/include/odp_packet_internal.h  | 140 +++++
>>>  .../linux-dpdk/include/odp_packet_io_internal.h    |  52 ++
>>>  platform/linux-dpdk/source/odp_buffer.c            | 102 ++++
>>>  platform/linux-dpdk/source/odp_buffer_pool.c       | 156 ++++++
>>>  platform/linux-dpdk/source/odp_init.c              | 113 +++++
>>>  platform/linux-dpdk/source/odp_packet.c            | 374 ++++++++++++++
>>>  platform/linux-dpdk/source/odp_packet_dpdk.c       | 177 +++++++
>>>  platform/linux-dpdk/source/odp_packet_io.c         | 561
>>> +++++++++++++++++++++
>>>  platform/linux-dpdk/source/odp_queue.c             | 435
>>> ++++++++++++++++
>>>  18 files changed, 3005 insertions(+)
>>>  create mode 100644 platform/linux-dpdk/Makefile
>>>  create mode 100644 platform/linux-dpdk/Makefile.inc
>>>  create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h
>>>  create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h
>>>  create mode 100644 platform/linux-dpdk/include/api/odp_packet.h
>>>  create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h
>>>  create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h
>>>  create mode 100644
>>> platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>>  create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h
>>>  create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h
>>>  create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h
>>>  create mode 100644 platform/linux-dpdk/source/odp_buffer.c
>>>  create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c
>>>  create mode 100644 platform/linux-dpdk/source/odp_init.c
>>>  create mode 100644 platform/linux-dpdk/source/odp_packet.c
>>>  create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c
>>>  create mode 100644 platform/linux-dpdk/source/odp_packet_io.c
>>>  create mode 100644 platform/linux-dpdk/source/odp_queue.c
>>>
>>> diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile
>>> new file mode 100644
>>> index 0000000..bf8d0b3
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/Makefile
>>> @@ -0,0 +1,158 @@
>>> +## Copyright (c) 2013, Linaro Limited
>>> +## All rights reserved.
>>> +##
>>> +## Redistribution and use in source and binary forms, with or without
>>> +## modification, are permitted provided that the following conditions
>>> are met:
>>> +##
>>> +##    * Redistributions of source code must retain the above copyright
>>> notice, this
>>> +##      list of conditions and the following disclaimer.
>>> +##
>>> +##    * Redistributions in binary form must reproduce the above
>>> copyright notice, this
>>> +##      list of conditions and the following disclaimer in the
>>> documentation and/or
>>> +##      other materials provided with the distribution.
>>> +##
>>> +##    * Neither the name of Linaro Limited nor the names of its
>>> contributors may be
>>> +##      used to endorse or promote products derived from this software
>>> without specific
>>> +##      prior written permission.
>>> +##
>>> +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>>> "AS IS" AND
>>> +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
>>> THE IMPLIED
>>> +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
>>> ARE
>>> +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
>>> BE LIABLE
>>> +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
>>> CONSEQUENTIAL
>>> +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
>>> GOODS OR
>>> +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
>>> HOWEVER
>>> +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
>>> LIABILITY,
>>> +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>>> OF THE USE
>>> +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>>> +
>>> +.DEFAULT_GOAL := libs
>>> +
>>> +ODP_ROOT = ../..
>>> +LIB_DIR  = ./lib
>>> +DOC_DIR  = ./doc
>>> +
>>> +LINUX_GENERIC_DIR = ../linux-generic
>>> +
>>> +RTE_SDK    ?= $(abspath $(ODP_ROOT)/../dpdk)
>>> +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build)
>>> +RTE_LIB    ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a)
>>> +
>>> +PLAT_CFLAGS  = -include $(RTE_OUTPUT)/include/rte_config.h
>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include
>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch
>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env
>>> +PLAT_CFLAGS += -msse4.2
>>> +
>>> +EXTRA_CFLAGS += $(PLAT_CFLAGS)
>>> +EXTRA_CFLAGS += -I./include
>>> +EXTRA_CFLAGS += -I./include/api
>>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include
>>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api
>>> +EXTRA_CFLAGS += -I$(ODP_ROOT)/include
>>> +
>>> +include $(ODP_ROOT)/Makefile.inc
>>> +STATIC_LIB = ./lib/libodp.a
>>> +
>>> +#
>>> +# Object files
>>> +#
>>> +OBJS     =
>>> +OBJS    += $(OBJ_DIR)/odp_barrier.o
>>> +OBJS    += $(OBJ_DIR)/odp_buffer.o
>>> +OBJS    += $(OBJ_DIR)/odp_buffer_pool.o
>>> +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
>>> +OBJS    += $(OBJ_DIR)/odp_schedule.o
>>> +OBJS    += $(OBJ_DIR)/odp_shared_memory.o
>>> +OBJS    += $(OBJ_DIR)/odp_spinlock.o
>>> +OBJS    += $(OBJ_DIR)/odp_system_info.o
>>> +OBJS    += $(OBJ_DIR)/odp_thread.o
>>> +OBJS    += $(OBJ_DIR)/odp_ticketlock.o
>>> +OBJS    += $(OBJ_DIR)/odp_time.o
>>> +OBJS    += $(OBJ_DIR)/odp_timer.o
>>> +OBJS    += $(OBJ_DIR)/odp_ring.o
>>> +OBJS    += $(OBJ_DIR)/odp_rwlock.o
>>> +OBJS    += $(OBJ_DIR)/odp_packet_dpdk.o
>>> +
>>> +DEPS     = $(OBJS:.o=.d)
>>> +
>>> +.PHONY: all
>>> +all: libs docs
>>> +
>>> +-include $(DEPS)
>>> +
>>> +#$(OBJ_DIR):
>>> +#      $(MKDIR) $(OBJ_DIR)
>>> +
>>> +$(LIB_DIR):
>>> +       $(MKDIR) $(LIB_DIR)
>>> +
>>> +$(DOC_DIR):
>>> +       $(MKDIR) $(DOC_DIR)/html
>>> +       $(MKDIR) $(DOC_DIR)/latex
>>> +
>>> +#
>>> +# Compile rules
>>> +#
>>> +vpath %.c source:$(LINUX_GENERIC_DIR)/source
>>> +
>>> +$(OBJ_DIR)/%.o: %.c
>>> +       $(ECHO) "  CC    $<"
>>> +       $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $<
>>> +
>>> +#
>>> +# Lib rule
>>> +#
>>> +$(OBJ_DIR)/libodp.o: $(OBJS)
>>> +       $(ECHO) "  LD    $@"
>>> +       $(LD) -r -o $@ $(OBJS) $(RTE_LIB)
>>> +
>>> +$(STATIC_LIB): $(OBJ_DIR)/libodp.o
>>> +       $(ECHO) "  AR    $@"
>>> +       $(AR) -cr $@ $(OBJ_DIR)/libodp.o
>>> +
>>> +
>>> +clean:
>>> +       $(RMDIR) $(OBJ_DIR)
>>> +       $(RMDIR) $(LIB_DIR)
>>> +       $(RMDIR) $(DOC_DIR)
>>> +       $(RM) Doxyfile
>>> +
>>> +Doxyfile: Doxyfile.in
>>> +       doxygen -u - < $< > $@
>>> +
>>> +.PHONY: docs
>>> +docs: $(DOC_DIR) Doxyfile ./include/odp*.h
>>> +       doxygen
>>> +
>>> +.PHONY: docs_install
>>> +docs_install: docs
>>> +       $(COPY) doc $(DESTDIR)
>>> +
>>> +.PHONY: pdf
>>> +pdf: docs
>>> +       make --directory doc/latex refman.pdf 1> /dev/null
>>> +
>>> +.PHONY: libs
>>> +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB)
>>> +
>>> +.PHONY: lib_install
>>> +lib_install: libs
>>> +       install -d $(DESTDIR)/lib
>>> +       install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/
>>> +
>>> +.PHONY: headers_install
>>> +headers_install: libs
>>> +       $(ECHO) Installing headers to $(DESTDIR)/include
>>> +       $(COPY) $(ODP_ROOT)/include $(DESTDIR)
>>> +       $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/
>>> +       $(COPY) include/api/* $(DESTDIR)/include/
>>> +
>>> +install: lib_install headers_install
>>> diff --git a/platform/linux-dpdk/Makefile.inc
>>> b/platform/linux-dpdk/Makefile.inc
>>> new file mode 100644
>>> index 0000000..fe7679b
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/Makefile.inc
>>> @@ -0,0 +1,7 @@
>>> +# Copyright (c) 2013, Linaro Limited
>>> +# All rights reserved.
>>> +#
>>> +# SPDX-License-Identifier:     BSD-3-Clause
>>> +
>>> +STD_LIBS += -ldl
>>> +
>>> diff --git a/platform/linux-dpdk/include/api/odp_buffer.h
>>> b/platform/linux-dpdk/include/api/odp_buffer.h
>>> new file mode 100644
>>> index 0000000..286d9e6
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/api/odp_buffer.h
>>> @@ -0,0 +1,101 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +
>>> +/**
>>> + * @file
>>> + *
>>> + * ODP buffer descriptor
>>> + */
>>> +
>>> +#ifndef ODP_BUFFER_H_
>>> +#define ODP_BUFFER_H_
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +
>>> +
>>> +#include <odp_std_types.h>
>>> +
>>> +
>>> +
>>> +
>>> +
>>> +/**
>>> + * ODP buffer
>>> + */
>>> +typedef unsigned long odp_buffer_t;
>>> +
>>> +
>>> +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */
>>> +
>>> +
>>> +/**
>>> + * Buffer start address
>>> + *
>>> + * @param buf      Buffer handle
>>> + *
>>> + * @return Buffer start address
>>> + */
>>> +void *odp_buffer_addr(odp_buffer_t buf);
>>> +
>>> +/**
>>> + * Buffer maximum data size
>>> + *
>>> + * @param buf      Buffer handle
>>> + *
>>> + * @return Buffer maximum data size
>>> + */
>>> +size_t odp_buffer_size(odp_buffer_t buf);
>>> +
>>> +/**
>>> + * Buffer type
>>> + *
>>> + * @param buf      Buffer handle
>>> + *
>>> + * @return Buffer type
>>> + */
>>> +int odp_buffer_type(odp_buffer_t buf);
>>> +
>>> +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */
>>> +#define ODP_BUFFER_TYPE_RAW       0  /**< Raw buffer */
>>> +#define ODP_BUFFER_TYPE_PACKET    1  /**< Packet buffer */
>>> +#define ODP_BUFFER_TYPE_TIMER     2  /**< Timer buffer */
>>> +
>>> +/**
>>> + * Tests if buffer is part of a scatter/gather list
>>> + *
>>> + * @param buf      Buffer handle
>>> + *
>>> + * @return 1 if belongs to a scatter list, otherwise 0
>>> + */
>>> +int odp_buffer_is_scatter(odp_buffer_t buf);
>>> +
>>> +/**
>>> + * Tests if buffer is valid
>>> + *
>>> + * @param buf      Buffer handle
>>> + *
>>> + * @return 1 if valid, otherwise 0
>>> + */
>>> +int odp_buffer_is_valid(odp_buffer_t buf);
>>> +
>>> +/**
>>> + * Print buffer metadata to STDOUT
>>> + *
>>> + * @param buf      Buffer handle
>>> + *
>>> + */
>>> +void odp_buffer_print(odp_buffer_t buf);
>>> +
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h
>>> b/platform/linux-dpdk/include/api/odp_buffer_pool.h
>>> new file mode 100644
>>> index 0000000..4b75cf5
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h
>>> @@ -0,0 +1,99 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +
>>> +/**
>>> + * @file
>>> + *
>>> + * ODP buffer pool
>>> + */
>>> +
>>> +#ifndef ODP_BUFFER_POOL_H_
>>> +#define ODP_BUFFER_POOL_H_
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +
>>> +
>>> +#include <odp_std_types.h>
>>> +#include <odp_buffer.h>
>>> +
>>> +/** Maximum queue name lenght in chars */
>>> +#define ODP_BUFFER_POOL_NAME_LEN  32
>>> +
>>> +/** Invalid buffer pool */
>>> +#define ODP_BUFFER_POOL_INVALID  (0xffffffff)
>>> +
>>> +/** ODP buffer pool */
>>> +typedef unsigned long odp_buffer_pool_t;
>>> +
>>> +
>>> +/**
>>> + * Create a buffer pool
>>> + *
>>> + * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1
>>> chars)
>>> + * @param base_addr Pool base address
>>> + * @param size      Pool size in bytes
>>> + * @param buf_size  Buffer size in bytes
>>> + * @param buf_align Minimum buffer alignment
>>> + * @param buf_type  Buffer type
>>> + *
>>> + * @return Buffer pool handle
>>> + */
>>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name,
>>> +                                        void *base_addr, uint64_t size,
>>> +                                        size_t buf_size, size_t
>>> buf_align,
>>> +                                        int buf_type);
>>> +
>>> +
>>> +/**
>>> + * Find a buffer pool by name
>>> + *
>>> + * @param name      Name of the pool
>>> + *
>>> + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
>>> + */
>>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name);
>>> +
>>> +
>>> +/**
>>> + * Print buffer pool info
>>> + *
>>> + * @param pool      Pool handle
>>> + *
>>> + */
>>> +void odp_buffer_pool_print(odp_buffer_pool_t pool);
>>> +
>>> +
>>> +
>>> +/**
>>> + * Buffer alloc
>>> + *
>>> + * @param pool      Pool handle
>>> + *
>>> + * @return Buffer handle or ODP_BUFFER_INVALID
>>> + */
>>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool);
>>> +
>>> +
>>> +/**
>>> + * Buffer free
>>> + *
>>> + * @param buf       Buffer handle
>>> + *
>>> + */
>>> +void odp_buffer_free(odp_buffer_t buf);
>>> +
>>> +
>>> +
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> diff --git a/platform/linux-dpdk/include/api/odp_packet.h
>>> b/platform/linux-dpdk/include/api/odp_packet.h
>>> new file mode 100644
>>> index 0000000..bdb3417
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/api/odp_packet.h
>>> @@ -0,0 +1,228 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +
>>> +/**
>>> + * @file
>>> + *
>>> + * ODP packet descriptor
>>> + */
>>> +
>>> +#ifndef ODP_PACKET_H_
>>> +#define ODP_PACKET_H_
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +#include <odp_buffer.h>
>>> +
>>> +
>>> +/**
>>> + * ODP packet descriptor
>>> + */
>>> +typedef unsigned long odp_packet_t;
>>> +
>>> +
>>> +/** Invalid packet */
>>> +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID
>>> +
>>> +/** Invalid offset */
>>> +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1)
>>> +
>>> +
>>> +/**
>>> + * Initialize the packet
>>> + *
>>> + * Needs to be called if the user allocates a packet buffer, i.e. the
>>> packet
>>> + * has not been received from I/O through ODP.
>>> + *
>>> + * @param pkt  Packet handle
>>> + */
>>> +void odp_packet_init(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Convert from packet handle to buffer handle
>>> + *
>>> + * @param buf  Buffer handle
>>> + *
>>> + * @return Packet handle
>>> + */
>>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf);
>>> +
>>> +/**
>>> + * Convert from buffer handle to packet handle
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return Buffer handle
>>> + */
>>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Set the packet length
>>> + *
>>> + * @param pkt  Packet handle
>>> + * @param len  Length of packet in bytes
>>> + */
>>> +void odp_packet_set_len(odp_packet_t pkt, size_t len);
>>> +
>>> +/**
>>> + * Get the packet length
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return   Packet length in bytes
>>> + */
>>> +size_t odp_packet_get_len(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Get address to the start of the packet buffer
>>> + *
>>> + * The address of the packet buffer is not necessarily the same as the
>>> start
>>> + * address of the received frame, e.g. an eth frame may be offset by 2
>>> or 6
>>> + * bytes to ensure 32 or 64-bit alignment of the IP header.
>>> + * Use odp_packet_l2(pkt) to get the start address of a received valid
>>> frame
>>> + * or odp_packet_start(pkt) to get the start address even if no valid
>>> L2 header
>>> + * could be found.
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return  Pointer to the start of the packet buffer
>>> + *
>>> + * @see odp_packet_l2(), odp_packet_start()
>>> + */
>>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Get pointer to the start of the received frame
>>> + *
>>> + * The address of the packet buffer is not necessarily the same as the
>>> start
>>> + * address of the received frame, e.g. an eth frame may be offset by 2
>>> or 6
>>> + * bytes to ensure 32 or 64-bit alignment of the IP header.
>>> + * Use odp_packet_l2(pkt) to get the start address of a received valid
>>> eth frame
>>> + *
>>> + * odp_packet_start() will always return a pointer to the start of the
>>> frame,
>>> + * even if the frame is unrecognized and no valid L2 header could be
>>> found.
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return  Pointer to the start of the received frame
>>> + *
>>> + * @see odp_packet_l2(), odp_packet_buf_addr()
>>> + */
>>> +uint8_t *odp_packet_start(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Get pointer to the start of the L2 frame
>>> + *
>>> + * The L2 frame header address is not necessarily the same as the
>>> address of the
>>> + * packet buffer, see odp_packet_buf_addr()
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return  Pointer to L2 header or NULL if not found
>>> + *
>>> + * @see odp_packet_buf_addr(), odp_packet_start()
>>> + */
>>> +uint8_t *odp_packet_l2(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Return the byte offset from the packet buffer to the L2 frame
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return  L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>>> + */
>>> +size_t odp_packet_l2_offset(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Set the byte offset to the L2 frame
>>> + *
>>> + * @param pkt     Packet handle
>>> + * @param offset  L2 byte offset
>>> + */
>>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset);
>>> +
>>> +
>>> +/**
>>> + * Get pointer to the start of the L3 packet
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return  Pointer to L3 packet or NULL if not found
>>> + *
>>> + */
>>> +uint8_t *odp_packet_l3(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Return the byte offset from the packet buffer to the L3 packet
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return  L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>>> + */
>>> +size_t odp_packet_l3_offset(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Set the byte offset to the L3 packet
>>> + *
>>> + * @param pkt     Packet handle
>>> + * @param offset  L3 byte offset
>>> + */
>>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset);
>>> +
>>> +
>>> +/**
>>> + * Get pointer to the start of the L4 packet
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return  Pointer to L4 packet or NULL if not found
>>> + *
>>> + */
>>> +uint8_t *odp_packet_l4(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Return the byte offset from the packet buffer to the L4 packet
>>> + *
>>> + * @param pkt  Packet handle
>>> + *
>>> + * @return  L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>>> + */
>>> +size_t odp_packet_l4_offset(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Set the byte offset to the L4 packet
>>> + *
>>> + * @param pkt     Packet handle
>>> + * @param offset  L4 byte offset
>>> + */
>>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset);
>>> +
>>> +/**
>>> + * Print (debug) information about the packet
>>> + *
>>> + * @param pkt  Packet handle
>>> + */
>>> +void odp_packet_print(odp_packet_t pkt);
>>> +
>>> +/**
>>> + * Copy contents and metadata from pkt_src to pkt_dst
>>> + * Useful when creating copies of packets
>>> + *
>>> + * @param pkt_dst Destination packet
>>> + * @param pkt_src Source packet
>>> + *
>>> + * @return 0 if successful
>>> + */
>>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src);
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h
>>> b/platform/linux-dpdk/include/api/odp_pktio_types.h
>>> new file mode 100644
>>> index 0000000..b23e6da
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h
>>> @@ -0,0 +1,45 @@
>>> +
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#ifndef ODP_PKTIO_TYPES_H
>>> +#define ODP_PKTIO_TYPES_H
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +/* We should ensure that future enum values will never overlap,
>>> otherwise
>>> + * applications that want netmap suport might get in trouble if the odp
>>> lib
>>> + * was not built with netmap support and there are more types define
>>> below
>>> + */
>>> +
>>> +typedef enum {
>>> +       ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1,
>>> +       ODP_PKTIO_TYPE_SOCKET_MMSG,
>>> +       ODP_PKTIO_TYPE_SOCKET_MMAP,
>>> +       ODP_PKTIO_TYPE_NETMAP,
>>> +       ODP_PKTIO_TYPE_DPDK,
>>> +} odp_pktio_type_t;
>>> +
>>> +#include <odp_pktio_socket.h>
>>> +#ifdef ODP_HAVE_NETMAP
>>> +#include <odp_pktio_netmap.h>
>>> +#endif
>>> +
>>> +typedef union odp_pktio_params_t {
>>> +       odp_pktio_type_t type;
>>> +       socket_params_t sock_params;
>>> +#ifdef ODP_HAVE_NETMAP
>>> +       netmap_params_t nm_params;
>>> +#endif
>>> +} odp_pktio_params_t;
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h
>>> b/platform/linux-dpdk/include/odp_buffer_internal.h
>>> new file mode 100644
>>> index 0000000..a47107c
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/odp_buffer_internal.h
>>> @@ -0,0 +1,79 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +
>>> +/**
>>> + * @file
>>> + *
>>> + * ODP buffer descriptor - implementation internal
>>> + */
>>> +
>>> +#ifndef ODP_BUFFER_INTERNAL_H_
>>> +#define ODP_BUFFER_INTERNAL_H_
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +#include <odp_std_types.h>
>>> +#include <odp_atomic.h>
>>> +#include <odp_buffer_pool.h>
>>> +#include <odp_buffer.h>
>>> +#include <odp_debug.h>
>>> +#include <odp_align.h>
>>> +#include <rte_mbuf.h>
>>> +
>>> +/* TODO: move these to correct files */
>>> +
>>> +typedef uint64_t odp_phys_addr_t;
>>> +
>>> +#define ODP_BUFFER_MAX_INDEX     (ODP_BUFFER_MAX_BUFFERS - 2)
>>> +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1)
>>> +
>>> +#define ODP_BUFS_PER_CHUNK       16
>>> +#define ODP_BUFS_PER_SCATTER      4
>>> +
>>> +#define ODP_BUFFER_TYPE_CHUNK    0xffff
>>> +
>>> +
>>> +#define ODP_BUFFER_POOL_BITS   4
>>> +#define ODP_BUFFER_INDEX_BITS  (32 - ODP_BUFFER_POOL_BITS)
>>> +#define ODP_BUFFER_MAX_POOLS   (1 << ODP_BUFFER_POOL_BITS)
>>> +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS)
>>> +
>>> +typedef union odp_buffer_bits_t {
>>> +       uint32_t     u32;
>>> +       odp_buffer_t handle;
>>> +
>>> +       struct {
>>> +               uint32_t pool:ODP_BUFFER_POOL_BITS;
>>> +               uint32_t index:ODP_BUFFER_INDEX_BITS;
>>> +       };
>>> +} odp_buffer_bits_t;
>>> +
>>> +
>>> +/* forward declaration */
>>> +struct odp_buffer_hdr_t;
>>> +
>>> +
>>> +typedef struct rte_mbuf odp_buffer_hdr_t;
>>> +
>>> +
>>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf);
>>> +
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> +
>>> +
>>> +
>>> +
>>> +
>>> +
>>> +
>>> diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>> b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>> new file mode 100644
>>> index 0000000..1a36655
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>> @@ -0,0 +1,90 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +
>>> +/**
>>> + * @file
>>> + *
>>> + * ODP buffer pool - internal header
>>> + */
>>> +
>>> +#ifndef ODP_BUFFER_POOL_INTERNAL_H_
>>> +#define ODP_BUFFER_POOL_INTERNAL_H_
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +#include <odp_std_types.h>
>>> +#include <odp_buffer_pool.h>
>>> +#include <odp_buffer_internal.h>
>>> +#include <odp_align.h>
>>> +#include <odp_hints.h>
>>> +#include <odp_config.h>
>>> +#include <odp_debug.h>
>>> +
>>> +/* for DPDK */
>>> +#include <rte_mempool.h>
>>> +
>>> +/* Use ticketlock instead of spinlock */
>>> +#define POOL_USE_TICKETLOCK
>>> +
>>> +/* Extra error checks */
>>> +/* #define POOL_ERROR_CHECK */
>>> +
>>> +
>>> +#ifdef POOL_USE_TICKETLOCK
>>> +#include <odp_ticketlock.h>
>>> +#else
>>> +#include <odp_spinlock.h>
>>> +#endif
>>> +
>>> +
>>> +struct pool_entry_s {
>>> +#ifdef POOL_USE_TICKETLOCK
>>> +       odp_ticketlock_t        lock ODP_ALIGNED_CACHE;
>>> +#else
>>> +       odp_spinlock_t          lock ODP_ALIGNED_CACHE;
>>> +#endif
>>> +
>>> +       uint64_t                free_bufs;
>>> +       char                    name[ODP_BUFFER_POOL_NAME_LEN];
>>> +
>>> +
>>> +       odp_buffer_pool_t       pool ODP_ALIGNED_CACHE;
>>> +       uintptr_t               buf_base;
>>> +       size_t                  buf_size;
>>> +       size_t                  buf_offset;
>>> +       uint64_t                num_bufs;
>>> +       void                   *pool_base_addr;
>>> +       uint64_t                pool_size;
>>> +       size_t                  payload_size;
>>> +       size_t                  payload_align;
>>> +       int                     buf_type;
>>> +       size_t                  hdr_size;
>>> +};
>>> +
>>> +
>>> +extern void *pool_entry_ptr[];
>>> +
>>> +
>>> +static inline void *get_pool_entry(odp_buffer_pool_t pool_id)
>>> +{
>>> +       return pool_entry_ptr[pool_id];
>>> +}
>>> +
>>> +
>>> +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf)
>>> +{
>>> +       return (odp_buffer_hdr_t *)buf;
>>> +}
>>> +
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h
>>> b/platform/linux-dpdk/include/odp_packet_dpdk.h
>>> new file mode 100644
>>> index 0000000..0b3db08
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
>>> @@ -0,0 +1,88 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#ifndef ODP_PACKET_DPDK_H
>>> +#define ODP_PACKET_DPDK_H
>>> +
>>> +#include <stdint.h>
>>> +#include <net/if.h>
>>> +
>>> +#include <helper/odp_eth.h>
>>> +#include <helper/odp_packet_helper.h>
>>> +#include <odp_align.h>
>>> +#include <odp_debug.h>
>>> +#include <odp_packet.h>
>>> +#include <odp_packet_internal.h>
>>> +#include <odp_buffer_pool.h>
>>> +#include <odp_buffer_pool_internal.h>
>>> +#include <odp_buffer_internal.h>
>>> +#include <odp_std_types.h>
>>> +
>>> +#include <rte_config.h>
>>> +#include <rte_memory.h>
>>> +#include <rte_memzone.h>
>>> +#include <rte_launch.h>
>>> +#include <rte_tailq.h>
>>> +#include <rte_eal.h>
>>> +#include <rte_per_lcore.h>
>>> +#include <rte_lcore.h>
>>> +#include <rte_branch_prediction.h>
>>> +#include <rte_prefetch.h>
>>> +#include <rte_cycles.h>
>>> +#include <rte_errno.h>
>>> +#include <rte_debug.h>
>>> +#include <rte_log.h>
>>> +#include <rte_byteorder.h>
>>> +#include <rte_pci.h>
>>> +#include <rte_random.h>
>>> +#include <rte_ether.h>
>>> +#include <rte_ethdev.h>
>>> +#include <rte_hash.h>
>>> +#include <rte_jhash.h>
>>> +#include <rte_hash_crc.h>
>>> +
>>> +
>>> +#define ODP_DPDK_MODE_HW       0
>>> +#define ODP_DPDK_MODE_SW       1
>>> +
>>> +#define DPDK_BLOCKING_IO
>>> +
>>> +/** Packet socket using dpdk mmaped rings for both Rx and Tx */
>>> +typedef struct {
>>> +       odp_buffer_pool_t pool;
>>> +
>>> +       /********************************/
>>> +       char ifname[32];
>>> +       uint8_t portid;
>>> +       uint16_t queueid;
>>> +} pkt_dpdk_t;
>>> +
>>> +/**
>>> + * Configure an interface to work in dpdk mode
>>> + */
>>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
>>> +                  odp_buffer_pool_t pool);
>>> +
>>> +/**
>>> + * Switch interface from dpdk mode to normal mode
>>> + */
>>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk);
>>> +
>>> +/**
>>> + * Receive packets using dpdk
>>> + */
>>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
>>> +                 unsigned len);
>>> +
>>> +/**
>>> + * Send packets using dpdk
>>> + */
>>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
>>> +                 unsigned len);
>>> +
>>> +int odp_init_dpdk(void);
>>> +#endif
>>> +
>>> diff --git a/platform/linux-dpdk/include/odp_packet_internal.h
>>> b/platform/linux-dpdk/include/odp_packet_internal.h
>>> new file mode 100644
>>> index 0000000..d9057a2
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/odp_packet_internal.h
>>> @@ -0,0 +1,140 @@
>>> +/* Copyright (c) 2014, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +
>>> +/**
>>> + * @file
>>> + *
>>> + * ODP packet descriptor - implementation internal
>>> + */
>>> +
>>> +#ifndef ODP_PACKET_INTERNAL_H_
>>> +#define ODP_PACKET_INTERNAL_H_
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +#include <odp_align.h>
>>> +#include <odp_debug.h>
>>> +#include <odp_buffer_internal.h>
>>> +#include <odp_buffer_pool_internal.h>
>>> +#include <odp_packet.h>
>>> +#include <odp_packet_io.h>
>>> +
>>> +/**
>>> + * Packet input & protocol flags
>>> + */
>>> +typedef union {
>>> +       /* All input flags */
>>> +       uint32_t all;
>>> +
>>> +       struct {
>>> +               /* 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:1;     /**< 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;
>>> +
>>> +       struct {
>>> +               /* 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;
>>> +
>>> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t),
>>> ERROR_FLAGS_SIZE_ERROR);
>>> +
>>> +/**
>>> + * Packet output flags
>>> + */
>>> +typedef union {
>>> +       /* All output flags */
>>> +       uint32_t all;
>>> +
>>> +       struct {
>>> +               /* 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 {
>>> +       /* common buffer header */
>>> +       odp_buffer_hdr_t buf_hdr;
>>> +
>>> +       input_flags_t  input_flags;
>>> +       error_flags_t  error_flags;
>>> +       output_flags_t output_flags;
>>> +
>>> +       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;
>>> +
>>> +/**
>>> + * Return the packet header
>>> + */
>>> +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt)
>>> +{
>>> +       return (odp_packet_hdr_t *)pkt;
>>> +}
>>> +
>>> +/**
>>> + * Parse packet and set internal metadata
>>> + */
>>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset);
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> +
>>> diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h
>>> b/platform/linux-dpdk/include/odp_packet_io_internal.h
>>> new file mode 100644
>>> index 0000000..5948063
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
>>> @@ -0,0 +1,52 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +
>>> +/**
>>> + * @file
>>> + *
>>> + * ODP packet IO - implementation internal
>>> + */
>>> +
>>> +#ifndef ODP_PACKET_IO_INTERNAL_H_
>>> +#define ODP_PACKET_IO_INTERNAL_H_
>>> +
>>> +#ifdef __cplusplus
>>> +extern "C" {
>>> +#endif
>>> +
>>> +#include <odp_spinlock.h>
>>> +#include <odp_packet_socket.h>
>>> +#ifdef ODP_HAVE_NETMAP
>>> +#include <odp_packet_netmap.h>
>>> +#endif
>>> +#include <odp_packet_dpdk.h>
>>> +
>>> +struct pktio_entry {
>>> +       odp_spinlock_t lock;            /**< entry spinlock */
>>> +       int taken;                      /**< is entry taken(1) or
>>> free(0) */
>>> +       odp_queue_t inq_default;        /**< default input queue, if set
>>> */
>>> +       odp_queue_t outq_default;       /**< default out queue */
>>> +       odp_pktio_params_t params;      /**< pktio parameters */
>>> +       pkt_sock_t pkt_sock;            /**< using socket API for IO */
>>> +       pkt_sock_mmap_t pkt_sock_mmap;  /**< using socket mmap API for
>>> IO */
>>> +#ifdef ODP_HAVE_NETMAP
>>> +       pkt_netmap_t pkt_nm;            /**< using netmap API for IO */
>>> +#endif
>>> +       pkt_dpdk_t pkt_dpdk;            /**< using DPDK API for IO */
>>> +};
>>> +
>>> +typedef union {
>>> +       struct pktio_entry s;
>>> +       uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct
>>> pktio_entry))];
>>> +} pktio_entry_t;
>>> +
>>> +#ifdef __cplusplus
>>> +}
>>> +#endif
>>> +
>>> +#endif
>>> +
>>> diff --git a/platform/linux-dpdk/source/odp_buffer.c
>>> b/platform/linux-dpdk/source/odp_buffer.c
>>> new file mode 100644
>>> index 0000000..bfb5ff6
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/source/odp_buffer.c
>>> @@ -0,0 +1,102 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#include <odp_buffer.h>
>>> +#include <odp_buffer_internal.h>
>>> +#include <odp_buffer_pool_internal.h>
>>> +
>>> +#include <string.h>
>>> +#include <stdio.h>
>>> +
>>> +
>>> +void *odp_buffer_addr(odp_buffer_t buf)
>>> +{
>>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>>> +
>>> +       return hdr->buf_addr;
>>> +}
>>> +
>>> +
>>> +size_t odp_buffer_size(odp_buffer_t buf)
>>> +{
>>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>>> +
>>> +       return hdr->buf_len;
>>> +}
>>> +
>>> +
>>> +int odp_buffer_type(odp_buffer_t buf)
>>> +{
>>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>>> +
>>> +       return hdr->type;
>>> +}
>>> +
>>> +
>>> +int odp_buffer_is_scatter(odp_buffer_t buf)
>>> +{
>>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>>> +
>>> +       if (hdr->refcnt == 0)
>>> +               return 0;
>>> +       else
>>> +               return 1;
>>> +}
>>> +
>>> +
>>> +int odp_buffer_is_valid(odp_buffer_t buf)
>>> +{
>>> +       odp_buffer_bits_t handle;
>>> +
>>> +       handle.u32 = buf;
>>> +
>>> +       return (handle.index != ODP_BUFFER_INVALID_INDEX);
>>> +}
>>> +
>>> +
>>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf)
>>> +{
>>> +       odp_buffer_hdr_t *hdr;
>>> +       int len = 0;
>>> +
>>> +       if (!odp_buffer_is_valid(buf)) {
>>> +               printf("Buffer is not valid.\n");
>>> +               return len;
>>> +       }
>>> +
>>> +       hdr = odp_buf_to_hdr(buf);
>>> +
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "Buffer\n");
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  pool         %"PRIu64"\n", (int64_t)
>>> hdr->pool);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  phy_addr     %"PRIu64"\n", hdr->buf_physaddr);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  addr         %p\n",        hdr->buf_addr);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  size         %u\n",        hdr->buf_len);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  ref_count    %i\n",        hdr->refcnt);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  type         %i\n",        hdr->type);
>>> +
>>> +       return len;
>>> +}
>>> +
>>> +
>>> +void odp_buffer_print(odp_buffer_t buf)
>>> +{
>>> +       int max_len = 512;
>>> +       char str[max_len];
>>> +       int len;
>>> +
>>> +       len = odp_buffer_snprint(str, max_len-1, buf);
>>> +       str[len] = 0;
>>> +
>>> +       printf("\n%s\n", str);
>>> +}
>>> +
>>> diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c
>>> b/platform/linux-dpdk/source/odp_buffer_pool.c
>>> new file mode 100644
>>> index 0000000..de90275
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/source/odp_buffer_pool.c
>>> @@ -0,0 +1,156 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#include <odp_std_types.h>
>>> +#include <odp_buffer_pool.h>
>>> +#include <odp_buffer_pool_internal.h>
>>> +#include <odp_buffer_internal.h>
>>> +#include <odp_packet_internal.h>
>>> +#include <odp_shared_memory.h>
>>> +#include <odp_align.h>
>>> +#include <odp_internal.h>
>>> +#include <odp_config.h>
>>> +#include <odp_hints.h>
>>> +#include <odp_debug.h>
>>> +
>>> +#include <string.h>
>>> +#include <stdlib.h>
>>> +
>>> +/* for DPDK */
>>> +#include <odp_packet_dpdk.h>
>>> +
>>> +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) +
>>> RTE_PKTMBUF_HEADROOM)
>>> +#define NB_MBUF   8192
>>> +
>>> +#ifdef POOL_USE_TICKETLOCK
>>> +#include <odp_ticketlock.h>
>>> +#define LOCK(a)      odp_ticketlock_lock(a)
>>> +#define UNLOCK(a)    odp_ticketlock_unlock(a)
>>> +#define LOCK_INIT(a) odp_ticketlock_init(a)
>>> +#else
>>> +#include <odp_spinlock.h>
>>> +#define LOCK(a)      odp_spinlock_lock(a)
>>> +#define UNLOCK(a)    odp_spinlock_unlock(a)
>>> +#define LOCK_INIT(a) odp_spinlock_init(a)
>>> +#endif
>>> +
>>> +
>>> +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
>>> +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
>>> +#endif
>>> +
>>> +#define NULL_INDEX ((uint32_t)-1)
>>> +
>>> +
>>> +typedef union pool_entry_u {
>>> +       struct pool_entry_s s;
>>> +
>>> +       uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct
>>> pool_entry_s))];
>>> +
>>> +} pool_entry_t;
>>> +
>>> +
>>> +typedef struct pool_table_t {
>>> +       pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS];
>>> +
>>> +} pool_table_t;
>>> +
>>> +
>>> +/* The pool table */
>>> +static pool_table_t *pool_tbl;
>>> +
>>> +/* Pool entry pointers (for inlining) */
>>> +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS];
>>> +
>>> +
>>> +int odp_buffer_pool_init_global(void)
>>> +{
>>> +       odp_buffer_pool_t i;
>>> +
>>> +       pool_tbl = odp_shm_reserve("odp_buffer_pools",
>>> +                                  sizeof(pool_table_t),
>>> +                                  sizeof(pool_entry_t));
>>> +
>>> +       if (pool_tbl == NULL)
>>> +               return -1;
>>> +
>>> +       memset(pool_tbl, 0, sizeof(pool_table_t));
>>> +
>>> +
>>> +       for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) {
>>> +               /* init locks */
>>> +               pool_entry_t *pool = &pool_tbl->pool[i];
>>> +               LOCK_INIT(&pool->s.lock);
>>> +               pool->s.pool = i;
>>> +
>>> +               pool_entry_ptr[i] = pool;
>>> +       }
>>> +
>>> +       ODP_DBG("\nBuffer pool init global\n");
>>> +       ODP_DBG("  pool_entry_s size     %zu\n", sizeof(struct
>>> pool_entry_s));
>>> +       ODP_DBG("  pool_entry_t size     %zu\n", sizeof(pool_entry_t));
>>> +       ODP_DBG("  odp_buffer_hdr_t size %zu\n",
>>> sizeof(odp_buffer_hdr_t));
>>> +       ODP_DBG("\n");
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +
>>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name,
>>> +                                        void *base_addr, uint64_t size,
>>> +                                        size_t buf_size, size_t
>>> buf_align,
>>> +                                        int buf_type)
>>> +{
>>> +       struct rte_mempool *pktmbuf_pool = NULL;
>>> +       ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n",
>>> name,
>>> +               (uint64_t) base_addr, (unsigned) size,
>>> +               (unsigned) buf_size, (unsigned) buf_align,
>>> +               buf_type);
>>> +
>>> +       pktmbuf_pool =
>>> +               rte_mempool_create(name, NB_MBUF,
>>> +                                  MBUF_SIZE, 32,
>>> +                                  sizeof(struct
>>> rte_pktmbuf_pool_private),
>>> +                                  rte_pktmbuf_pool_init, NULL,
>>> +                                  rte_pktmbuf_init, NULL,
>>> +                                  rte_socket_id(), 0);
>>> +       if (pktmbuf_pool == NULL) {
>>> +               ODP_ERR("Cannot init DPDK mbuf pool\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       return (odp_buffer_pool_t) pktmbuf_pool;
>>> +}
>>> +
>>> +
>>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name)
>>> +{
>>> +       struct rte_mempool *mp = NULL;
>>> +
>>> +       mp = rte_mempool_lookup(name);
>>> +       if (mp == NULL)
>>> +               return ODP_BUFFER_POOL_INVALID;
>>> +
>>> +       return (odp_buffer_pool_t)mp;
>>> +}
>>> +
>>> +
>>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id)
>>> +{
>>> +       return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool
>>> *)pool_id);
>>> +}
>>> +
>>> +
>>> +void odp_buffer_free(odp_buffer_t buf)
>>> +{
>>> +       rte_pktmbuf_free((struct rte_mbuf *)buf);
>>> +}
>>> +
>>> +
>>> +void odp_buffer_pool_print(odp_buffer_pool_t pool_id)
>>> +{
>>> +       rte_mempool_dump((const struct rte_mempool *)pool_id);
>>> +}
>>> diff --git a/platform/linux-dpdk/source/odp_init.c
>>> b/platform/linux-dpdk/source/odp_init.c
>>> new file mode 100644
>>> index 0000000..ecc2066
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/source/odp_init.c
>>> @@ -0,0 +1,113 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#include <odp_init.h>
>>> +#include <odp_internal.h>
>>> +#include <odp_debug.h>
>>> +#include <odp_packet_dpdk.h>
>>> +
>>> +int odp_init_dpdk(void)
>>> +{
>>> +       int test_argc = 5;
>>> +       char *test_argv[6];
>>> +       int core_count, i, num_cores = 0;
>>> +       char core_mask[8];
>>> +
>>> +       core_count  = odp_sys_core_count();
>>> +       for (i = 0; i < core_count; i++)
>>> +               num_cores += (0x1 << i);
>>> +       sprintf(core_mask, "%x", num_cores);
>>> +
>>> +       test_argv[0] = malloc(sizeof("odp_dpdk"));
>>> +       strcpy(test_argv[0], "odp_dpdk");
>>> +       test_argv[1] = malloc(sizeof("-c"));
>>> +       strcpy(test_argv[1], "-c");
>>> +       test_argv[2] = malloc(sizeof(core_mask));
>>> +       strcpy(test_argv[2], core_mask);
>>> +       test_argv[3] = malloc(sizeof("-n"));
>>> +       strcpy(test_argv[3], "-n");
>>> +       test_argv[4] = malloc(sizeof("3"));
>>> +       strcpy(test_argv[4], "3");
>>> +
>>> +       if (rte_eal_init(test_argc, (char **)test_argv) < 0) {
>>> +               ODP_ERR("Cannot init the Intel DPDK EAL!");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (rte_pmd_init_all() < 0) {
>>> +               ODP_ERR("Cannot init pmd\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (rte_eal_pci_probe() < 0) {
>>> +               ODP_ERR("Cannot probe PCI\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +int odp_init_global(void)
>>> +{
>>> +       odp_thread_init_global();
>>> +
>>> +       odp_system_info_init();
>>> +
>>> +       if (odp_init_dpdk()) {
>>> +               ODP_ERR("ODP dpdk init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (odp_shm_init_global()) {
>>> +               ODP_ERR("ODP shm init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (odp_buffer_pool_init_global()) {
>>> +               ODP_ERR("ODP buffer pool init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (odp_queue_init_global()) {
>>> +               ODP_ERR("ODP queue init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (odp_schedule_init_global()) {
>>> +               ODP_ERR("ODP schedule init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (odp_pktio_init_global()) {
>>> +               ODP_ERR("ODP packet io init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (odp_timer_init_global()) {
>>> +               ODP_ERR("ODP timer init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +
>>> +int odp_init_local(int thr_id)
>>> +{
>>> +       odp_thread_init_local(thr_id);
>>> +
>>> +       if (odp_pktio_init_local()) {
>>> +               ODP_ERR("ODP packet io local init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       if (odp_schedule_init_local()) {
>>> +               ODP_ERR("ODP schedule local init failed.\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> diff --git a/platform/linux-dpdk/source/odp_packet.c
>>> b/platform/linux-dpdk/source/odp_packet.c
>>> new file mode 100644
>>> index 0000000..c34e626
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/source/odp_packet.c
>>> @@ -0,0 +1,374 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#include <odp_packet.h>
>>> +#include <odp_packet_internal.h>
>>> +#include <odp_hints.h>
>>> +#include <odp_byteorder.h>
>>> +
>>> +#include <helper/odp_eth.h>
>>> +#include <helper/odp_ip.h>
>>> +
>>> +#include <string.h>
>>> +#include <stdio.h>
>>> +
>>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
>>> odp_ipv4hdr_t *ipv4,
>>> +                               size_t *offset_out);
>>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
>>> odp_ipv6hdr_t *ipv6,
>>> +                               size_t *offset_out);
>>> +
>>> +void odp_packet_init(odp_packet_t pkt)
>>> +{
>>> +       odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
>>> +       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>>> buf_hdr);
>>> +       uint8_t *start;
>>> +       size_t len;
>>> +
>>> +       start = (uint8_t *)pkt_hdr + start_offset;
>>> +       len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
>>> +       memset(start, 0, len);
>>> +
>>> +       pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>>> +       pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>>> +       pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>>> +}
>>> +
>>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf)
>>> +{
>>> +       return (odp_packet_t)buf;
>>> +}
>>> +
>>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt)
>>> +{
>>> +       return (odp_buffer_t)pkt;
>>> +}
>>> +
>>> +void odp_packet_set_len(odp_packet_t pkt, size_t len)
>>> +{
>>> +       /* for rte_pktmbuf */
>>> +       odp_buffer_hdr_t *buf_hdr =
>>> odp_buf_to_hdr(odp_buffer_from_packet(pkt));
>>> +       buf_hdr->pkt.data_len = len;
>>> +
>>> +       odp_packet_hdr(pkt)->frame_len = len;
>>> +}
>>> +
>>> +size_t odp_packet_get_len(odp_packet_t pkt)
>>> +{
>>> +       return odp_packet_hdr(pkt)->frame_len;
>>> +}
>>> +
>>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt)
>>> +{
>>> +       return odp_buffer_addr(odp_buffer_from_packet(pkt));
>>> +}
>>> +
>>> +uint8_t *odp_packet_start(odp_packet_t pkt)
>>> +{
>>> +       return odp_packet_buf_addr(pkt) +
>>> odp_packet_hdr(pkt)->frame_offset;
>>> +}
>>> +
>>> +
>>> +uint8_t *odp_packet_l2(odp_packet_t pkt)
>>> +{
>>> +       const size_t offset = odp_packet_l2_offset(pkt);
>>> +
>>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>>> +               return NULL;
>>> +
>>> +       return odp_packet_buf_addr(pkt) + offset;
>>> +}
>>> +
>>> +size_t odp_packet_l2_offset(odp_packet_t pkt)
>>> +{
>>> +       return odp_packet_hdr(pkt)->l2_offset;
>>> +}
>>> +
>>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset)
>>> +{
>>> +       odp_packet_hdr(pkt)->l2_offset = offset;
>>> +}
>>> +
>>> +uint8_t *odp_packet_l3(odp_packet_t pkt)
>>> +{
>>> +       const size_t offset = odp_packet_l3_offset(pkt);
>>> +
>>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>>> +               return NULL;
>>> +
>>> +       return odp_packet_buf_addr(pkt) + offset;
>>> +}
>>> +
>>> +size_t odp_packet_l3_offset(odp_packet_t pkt)
>>> +{
>>> +       return odp_packet_hdr(pkt)->l3_offset;
>>> +}
>>> +
>>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset)
>>> +{
>>> +       odp_packet_hdr(pkt)->l3_offset = offset;
>>> +}
>>> +
>>> +uint8_t *odp_packet_l4(odp_packet_t pkt)
>>> +{
>>> +       const size_t offset = odp_packet_l4_offset(pkt);
>>> +
>>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>>> +               return NULL;
>>> +
>>> +       return odp_packet_buf_addr(pkt) + offset;
>>> +}
>>> +
>>> +size_t odp_packet_l4_offset(odp_packet_t pkt)
>>> +{
>>> +       return odp_packet_hdr(pkt)->l4_offset;
>>> +}
>>> +
>>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset)
>>> +{
>>> +       odp_packet_hdr(pkt)->l4_offset = offset;
>>> +}
>>> +
>>> +/**
>>> + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP
>>> + *
>>> + * Internal function: caller is resposible for passing only valid
>>> packet handles
>>> + * , lengths and offsets (usually done&called in packet input).
>>> + *
>>> + * @param pkt        Packet handle
>>> + * @param len        Packet length in bytes
>>> + * @param frame_offset  Byte offset to L2 header
>>> + */
>>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset)
>>> +{
>>> +       odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
>>> +       odp_ethhdr_t *eth;
>>> +       odp_vlanhdr_t *vlan;
>>> +       odp_ipv4hdr_t *ipv4;
>>> +       odp_ipv6hdr_t *ipv6;
>>> +       uint16_t ethtype;
>>> +       size_t offset = 0;
>>> +       uint8_t ip_proto = 0;
>>> +
>>> +       pkt_hdr->input_flags.eth = 1;
>>> +       pkt_hdr->frame_offset = frame_offset;
>>> +       pkt_hdr->frame_len = len;
>>> +
>>> +       if (odp_unlikely(len < ODP_ETH_LEN_MIN)) {
>>> +               pkt_hdr->error_flags.frame_len = 1;
>>> +               return;
>>> +       } else if (len > ODP_ETH_LEN_MAX) {
>>> +               pkt_hdr->input_flags.jumbo = 1;
>>> +       }
>>> +
>>> +       /* Assume valid L2 header, no CRC/FCS check in SW */
>>> +       pkt_hdr->input_flags.l2 = 1;
>>> +       pkt_hdr->l2_offset = frame_offset;
>>> +
>>> +       eth = (odp_ethhdr_t *)odp_packet_start(pkt);
>>> +       ethtype = odp_be_to_cpu_16(eth->type);
>>> +       vlan = (odp_vlanhdr_t *)&eth->type;
>>> +
>>> +       if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
>>> +               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->input_flags.vlan = 1;
>>> +               ethtype = odp_be_to_cpu_16(vlan->tpid);
>>> +               offset += sizeof(odp_vlanhdr_t);
>>> +       }
>>> +
>>> +       /* Set l3_offset+flag only for known ethtypes */
>>> +       switch (ethtype) {
>>> +       case ODP_ETHTYPE_IPV4:
>>> +               pkt_hdr->input_flags.ipv4 = 1;
>>> +               pkt_hdr->input_flags.l3 = 1;
>>> +               pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN +
>>> offset;
>>> +               ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
>>> +               ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset);
>>> +               break;
>>> +       case ODP_ETHTYPE_IPV6:
>>> +               pkt_hdr->input_flags.ipv6 = 1;
>>> +               pkt_hdr->input_flags.l3 = 1;
>>> +               pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN +
>>> offset;
>>> +               ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt);
>>> +               ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset);
>>> +               break;
>>> +       case ODP_ETHTYPE_ARP:
>>> +               pkt_hdr->input_flags.arp = 1;
>>> +               /* fall through */
>>> +       default:
>>> +               ip_proto = 0;
>>> +               break;
>>> +       }
>>> +
>>> +       switch (ip_proto) {
>>> +       case ODP_IPPROTO_UDP:
>>> +               pkt_hdr->input_flags.udp = 1;
>>> +               pkt_hdr->input_flags.l4 = 1;
>>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>>> +               break;
>>> +       case ODP_IPPROTO_TCP:
>>> +               pkt_hdr->input_flags.tcp = 1;
>>> +               pkt_hdr->input_flags.l4 = 1;
>>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>>> +               break;
>>> +       case ODP_IPPROTO_SCTP:
>>> +               pkt_hdr->input_flags.sctp = 1;
>>> +               pkt_hdr->input_flags.l4 = 1;
>>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>>> +               break;
>>> +       case ODP_IPPROTO_ICMP:
>>> +               pkt_hdr->input_flags.icmp = 1;
>>> +               pkt_hdr->input_flags.l4 = 1;
>>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>>> +               break;
>>> +       default:
>>> +               /* 0 or unhandled IP protocols, don't set L4 flag+offset
>>> */
>>> +               if (pkt_hdr->input_flags.ipv6) {
>>> +                       /* IPv6 next_hdr is not L4, mark as IP-option
>>> instead */
>>> +                       pkt_hdr->input_flags.ipopt = 1;
>>> +               }
>>> +               break;
>>> +       }
>>> +}
>>> +
>>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
>>> odp_ipv4hdr_t *ipv4,
>>> +                               size_t *offset_out)
>>> +{
>>> +       uint8_t ihl;
>>> +       uint16_t frag_offset;
>>> +
>>> +       ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl);
>>> +       if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) {
>>> +               pkt_hdr->error_flags.ip_err = 1;
>>> +               return 0;
>>> +       }
>>> +
>>> +       if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) {
>>> +               pkt_hdr->input_flags.ipopt = 1;
>>> +               return 0;
>>> +       }
>>> +
>>> +       /* A packet is a fragment if:
>>> +       *  "more fragments" flag is set (all fragments except the last)
>>> +       *     OR
>>> +       *  "fragment offset" field is nonzero (all fragments except the
>>> first)
>>> +       */
>>> +       frag_offset = odp_be_to_cpu_16(ipv4->frag_offset);
>>> +       if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) {
>>> +               pkt_hdr->input_flags.ipfrag = 1;
>>> +               return 0;
>>> +       }
>>> +
>>> +       if (ipv4->proto == ODP_IPPROTO_ESP ||
>>> +           ipv4->proto == ODP_IPPROTO_AH) {
>>> +               pkt_hdr->input_flags.ipsec = 1;
>>> +               return 0;
>>> +       }
>>> +
>>> +       /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after
>>> return */
>>> +
>>> +       *offset_out = sizeof(uint32_t) * ihl;
>>> +       return ipv4->proto;
>>> +}
>>> +
>>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
>>> odp_ipv6hdr_t *ipv6,
>>> +                               size_t *offset_out)
>>> +{
>>> +       if (ipv6->next_hdr == ODP_IPPROTO_ESP ||
>>> +           ipv6->next_hdr == ODP_IPPROTO_AH) {
>>> +               pkt_hdr->input_flags.ipopt = 1;
>>> +               pkt_hdr->input_flags.ipsec = 1;
>>> +               return 0;
>>> +       }
>>> +
>>> +       if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) {
>>> +               pkt_hdr->input_flags.ipopt = 1;
>>> +               pkt_hdr->input_flags.ipfrag = 1;
>>> +               return 0;
>>> +       }
>>> +
>>> +       /* Don't step through more extensions */
>>> +       *offset_out = ODP_IPV6HDR_LEN;
>>> +       return ipv6->next_hdr;
>>> +}
>>> +
>>> +void odp_packet_print(odp_packet_t pkt)
>>> +{
>>> +       int max_len = 512;
>>> +       char str[max_len];
>>> +       int len = 0;
>>> +       int n = max_len-1;
>>> +       odp_packet_hdr_t *hdr = odp_packet_hdr(pkt);
>>> +
>>> +       len += snprintf(&str[len], n-len, "Packet ");
>>> +       len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  input_flags  0x%x\n", hdr->input_flags.all);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  error_flags  0x%x\n", hdr->error_flags.all);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  output_flags 0x%x\n", hdr->output_flags.all);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  frame_offset %u\n", hdr->frame_offset);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  l2_offset    %u\n", hdr->l2_offset);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  l3_offset    %u\n", hdr->l3_offset);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  l4_offset    %u\n", hdr->l4_offset);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  frame_len    %u\n", hdr->frame_len);
>>> +       len += snprintf(&str[len], n-len,
>>> +                       "  input        %u\n", hdr->input);
>>> +       str[len] = '\0';
>>> +
>>> +       printf("\n%s\n", str);
>>> +}
>>> +
>>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src)
>>> +{
>>> +       odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst);
>>> +       odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src);
>>> +       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>>> buf_hdr);
>>> +       uint8_t *start_src;
>>> +       uint8_t *start_dst;
>>> +       size_t len;
>>> +
>>> +       if (pkt_dst == ODP_PACKET_INVALID || pkt_src ==
>>> ODP_PACKET_INVALID)
>>> +               return -1;
>>> +
>>> +       /* if (pkt_hdr_dst->buf_hdr.size < */
>>> +       /*      pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */
>>> +       if (pkt_hdr_dst->buf_hdr.buf_len <
>>> +               pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset)
>>> +               return -1;
>>> +
>>> +       /* Copy packet header */
>>> +       start_dst = (uint8_t *)pkt_hdr_dst + start_offset;
>>> +       start_src = (uint8_t *)pkt_hdr_src + start_offset;
>>> +       len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
>>> +       memcpy(start_dst, start_src, len);
>>> +
>>> +       /* Copy frame payload */
>>> +       start_dst = (uint8_t *)odp_packet_start(pkt_dst);
>>> +       start_src = (uint8_t *)odp_packet_start(pkt_src);
>>> +       len = pkt_hdr_src->frame_len;
>>> +       memcpy(start_dst, start_src, len);
>>> +
>>> +       /* Copy useful things from the buffer header */
>>> +       /* pkt_hdr_dst->buf_hdr.cur_offset =
>>> pkt_hdr_src->buf_hdr.cur_offset; */
>>> +
>>> +       /* Create a copy of the scatter list */
>>> +       /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */
>>> +       /*                      odp_buffer_from_packet(pkt_src)); */
>>> +
>>> +       return 0;
>>> +}
>>> diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c
>>> b/platform/linux-dpdk/source/odp_packet_dpdk.c
>>> new file mode 100644
>>> index 0000000..6d16bbe
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c
>>> @@ -0,0 +1,177 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#define _GNU_SOURCE
>>> +#include <stdio.h>
>>> +#include <errno.h>
>>> +#include <sys/types.h>
>>> +#include <sys/stat.h>
>>> +#include <sys/ioctl.h>
>>> +#include <sys/mman.h>
>>> +#include <poll.h>
>>> +#include <unistd.h>
>>> +#include <fcntl.h>
>>> +#include <string.h>
>>> +#include <stdlib.h>
>>> +
>>> +#include <linux/ethtool.h>
>>> +#include <linux/sockios.h>
>>> +
>>> +#include <odp_hints.h>
>>> +#include <odp_thread.h>
>>> +
>>> +#include <odp_packet_dpdk.h>
>>> +#include <net/if.h>
>>> +
>>> +/*
>>> + * RX and TX Prefetch, Host, and Write-back threshold values should be
>>> + * carefully set for optimal performance. Consult the network
>>> + * controller's datasheet and supporting DPDK documentation for guidance
>>> + * on how these parameters should be set.
>>> + */
>>> +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg.
>>> */
>>> +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
>>> +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold
>>> reg. */
>>> +
>>> +/*
>>> + * These default values are optimized for use with the Intel(R) 82599
>>> 10 GbE
>>> + * Controller and the DPDK ixgbe PMD. Consider using other values for
>>> other
>>> + * network controllers and/or network drivers.
>>> + */
>>> +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg.
>>> */
>>> +#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
>>> +#define TX_WTHRESH 0  /**< Default values of TX write-back threshold
>>> reg. */
>>> +
>>> +#define MAX_PKT_BURST 32
>>> +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
>>> +#define RTE_TEST_RX_DESC_DEFAULT 128
>>> +#define RTE_TEST_TX_DESC_DEFAULT 512
>>> +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
>>> +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
>>> +
>>> +static const struct rte_eth_conf port_conf = {
>>> +       .rxmode = {
>>> +               .split_hdr_size = 0,
>>> +               .header_split   = 0, /**< Header Split disabled */
>>> +               .hw_ip_checksum = 0, /**< IP checksum offload disabled */
>>> +               .hw_vlan_filter = 0, /**< VLAN filtering disabled */
>>> +               .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
>>> +               .hw_strip_crc   = 0, /**< CRC stripped by hardware */
>>> +       },
>>> +       .txmode = {
>>> +               .mq_mode = ETH_MQ_TX_NONE,
>>> +       },
>>> +};
>>> +
>>> +static const struct rte_eth_rxconf rx_conf = {
>>> +       .rx_thresh = {
>>> +               .pthresh = RX_PTHRESH,
>>> +               .hthresh = RX_HTHRESH,
>>> +               .wthresh = RX_WTHRESH,
>>> +       },
>>> +};
>>> +
>>> +static const struct rte_eth_txconf tx_conf = {
>>> +       .tx_thresh = {
>>> +               .pthresh = TX_PTHRESH,
>>> +               .hthresh = TX_HTHRESH,
>>> +               .wthresh = TX_WTHRESH,
>>> +       },
>>> +       .tx_free_thresh = 0, /* Use PMD default values */
>>> +       .tx_rs_thresh = 0, /* Use PMD default values */
>>> +       /*
>>> +        * As the example won't handle mult-segments and offload cases,
>>> +        * set the flag by default.
>>> +        */
>>> +       .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS,
>>> +};
>>> +
>>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
>>> +               odp_buffer_pool_t pool)
>>> +{
>>> +       ODP_DBG("setup_pkt_dpdk\n");
>>> +
>>> +       static struct ether_addr eth_addr[RTE_MAX_ETHPORTS];
>>> +       uint8_t portid = 0;
>>> +       uint16_t queueid = 0;
>>> +       int ret;
>>> +       printf("vincent netdev: %s\n", netdev);
>>> +       printf("vincent pool: %lx\n", pool);
>>> +
>>> +       portid = atoi(netdev);
>>> +       pkt_dpdk->portid = portid;
>>> +       pkt_dpdk->queueid = queueid;
>>> +       pkt_dpdk->pool = pool;
>>> +       printf("vincent portid: %u\n", portid);
>>> +
>>> +       fflush(stdout);
>>> +       ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
>>> +       if (ret < 0)
>>> +               ODP_ERR("Cannot configure device: err=%d, port=%u\n",
>>> +                       ret, (unsigned) portid);
>>> +
>>> +       rte_eth_macaddr_get(portid, &eth_addr[portid]);
>>> +       ODP_DBG("Port %u, MAC address:
>>> %02X:%02X:%02X:%02X:%02X:%02X\n\n",
>>> +               (unsigned) portid,
>>> +               eth_addr[portid].addr_bytes[0],
>>> +               eth_addr[portid].addr_bytes[1],
>>> +               eth_addr[portid].addr_bytes[2],
>>> +               eth_addr[portid].addr_bytes[3],
>>> +               eth_addr[portid].addr_bytes[4],
>>> +               eth_addr[portid].addr_bytes[5]);
>>> +
>>> +       /* init one RX queue on each port */
>>> +       fflush(stdout);
>>> +       ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
>>> +                                    rte_eth_dev_socket_id(portid),
>>> &rx_conf,
>>> +                                    (struct rte_mempool *)pool);
>>> +       if (ret < 0)
>>> +               ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n",
>>> +                       ret, (unsigned) portid);
>>> +       ODP_DBG("dpdk rx queue setup done\n");
>>> +
>>> +       /* init one TX queue on each port */
>>> +       fflush(stdout);
>>> +       ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
>>> +                       rte_eth_dev_socket_id(portid), &tx_conf);
>>> +       if (ret < 0)
>>> +               ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n",
>>> +                       ret, (unsigned) portid);
>>> +       ODP_DBG("dpdk tx queue setup done\n");
>>> +
>>> +       /* Start device */
>>> +       ret = rte_eth_dev_start(portid);
>>> +       if (ret < 0)
>>> +               ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n",
>>> +                       ret, (unsigned) portid);
>>> +       ODP_DBG("dpdk setup done\n\n");
>>> +
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk)
>>> +{
>>> +       ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
>>> +               unsigned len)
>>> +{
>>> +       return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid,
>>> +                               (uint16_t)pkt_dpdk->queueid,
>>> +                               (struct rte_mbuf **)pkt_table,
>>> (uint16_t)len);
>>> +}
>>> +
>>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
>>> +               unsigned len)
>>> +{
>>> +       return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid,
>>> +                               (uint16_t)pkt_dpdk->queueid,
>>> +                               (struct rte_mbuf **)pkt_table,
>>> (uint16_t)len);
>>> +}
>>> diff --git a/platform/linux-dpdk/source/odp_packet_io.c
>>> b/platform/linux-dpdk/source/odp_packet_io.c
>>> new file mode 100644
>>> index 0000000..abea0ec
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/source/odp_packet_io.c
>>> @@ -0,0 +1,561 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#include <odp_packet_io.h>
>>> +#include <odp_packet_io_internal.h>
>>> +#include <odp_packet_io_queue.h>
>>> +#include <odp_packet.h>
>>> +#include <odp_packet_internal.h>
>>> +#include <odp_internal.h>
>>> +#include <odp_spinlock.h>
>>> +#include <odp_shared_memory.h>
>>> +#include <odp_packet_socket.h>
>>> +#ifdef ODP_HAVE_NETMAP
>>> +#include <odp_packet_netmap.h>
>>> +#endif
>>> +#include <odp_hints.h>
>>> +#include <odp_config.h>
>>> +#include <odp_queue_internal.h>
>>> +#include <odp_schedule_internal.h>
>>> +#include <odp_debug.h>
>>> +
>>> +#include <odp_pktio_socket.h>
>>> +#ifdef ODP_HAVE_NETMAP
>>> +#include <odp_pktio_netmap.h>
>>> +#endif
>>> +
>>> +#include <string.h>
>>> +
>>> +typedef struct {
>>> +       pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
>>> +} pktio_table_t;
>>> +
>>> +static pktio_table_t *pktio_tbl;
>>> +
>>> +
>>> +static pktio_entry_t *get_entry(odp_pktio_t id)
>>> +{
>>> +       if (odp_unlikely(id == ODP_PKTIO_INVALID ||
>>> +                        id > ODP_CONFIG_PKTIO_ENTRIES))
>>> +               return NULL;
>>> +
>>> +       return &pktio_tbl->entries[id - 1];
>>> +}
>>> +
>>> +int odp_pktio_init_global(void)
>>> +{
>>> +       char name[ODP_QUEUE_NAME_LEN];
>>> +       pktio_entry_t *pktio_entry;
>>> +       queue_entry_t *queue_entry;
>>> +       odp_queue_t qid;
>>> +       int id;
>>> +
>>> +       pktio_tbl = odp_shm_reserve("odp_pktio_entries",
>>> +                                   sizeof(pktio_table_t),
>>> +                                   sizeof(pktio_entry_t));
>>> +       if (pktio_tbl == NULL)
>>> +               return -1;
>>> +
>>> +       memset(pktio_tbl, 0, sizeof(pktio_table_t));
>>> +
>>> +       for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
>>> +               pktio_entry = get_entry(id);
>>> +
>>> +               odp_spinlock_init(&pktio_entry->s.lock);
>>> +
>>> +               /* Create a default output queue for each pktio resource
>>> */
>>> +               snprintf(name, sizeof(name), "%i-pktio_outq_default",
>>> (int)id);
>>> +               name[ODP_QUEUE_NAME_LEN-1] = '\0';
>>> +
>>> +               qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT,
>>> NULL);
>>> +               if (qid == ODP_QUEUE_INVALID)
>>> +                       return -1;
>>> +               pktio_entry->s.outq_default = qid;
>>> +
>>> +               queue_entry = queue_to_qentry(qid);
>>> +               queue_entry->s.pktout = id;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +int odp_pktio_init_local(void)
>>> +{
>>> +       return 0;
>>> +}
>>> +
>>> +static int is_free(pktio_entry_t *entry)
>>> +{
>>> +       return (entry->s.taken == 0);
>>> +}
>>> +
>>> +static void set_free(pktio_entry_t *entry)
>>> +{
>>> +       entry->s.taken = 0;
>>> +}
>>> +
>>> +static void set_taken(pktio_entry_t *entry)
>>> +{
>>> +       entry->s.taken = 1;
>>> +}
>>> +
>>> +static void lock_entry(pktio_entry_t *entry)
>>> +{
>>> +       odp_spinlock_lock(&entry->s.lock);
>>> +}
>>> +
>>> +static void unlock_entry(pktio_entry_t *entry)
>>> +{
>>> +       odp_spinlock_unlock(&entry->s.lock);
>>> +}
>>> +
>>> +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t
>>> *params)
>>> +{
>>> +       set_taken(entry);
>>> +       entry->s.inq_default = ODP_QUEUE_INVALID;
>>> +       switch (params->type) {
>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>> +               memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock));
>>> +               memset(&entry->s.pkt_sock_mmap, 0,
>>> +                      sizeof(entry->s.pkt_sock_mmap));
>>> +               break;
>>> +#ifdef ODP_HAVE_NETMAP
>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>> +               memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm));
>>> +               break;
>>> +#endif
>>> +       case ODP_PKTIO_TYPE_DPDK:
>>> +               memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk));
>>> +               break;
>>> +       default:
>>> +               ODP_ERR("Packet I/O type not supported. Please
>>> recompile\n");
>>> +               break;
>>> +       }
>>> +       /* Save pktio parameters, type is the most useful */
>>> +       memcpy(&entry->s.params, params, sizeof(*params));
>>> +}
>>> +
>>> +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
>>> +{
>>> +       odp_pktio_t id;
>>> +       pktio_entry_t *entry;
>>> +       int i;
>>> +
>>> +       for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
>>> +               entry = &pktio_tbl->entries[i];
>>> +               if (is_free(entry)) {
>>> +                       lock_entry(entry);
>>> +                       if (is_free(entry)) {
>>> +                               init_pktio_entry(entry, params);
>>> +                               id = i + 1;
>>> +                               return id; /* return with entry locked!
>>> */
>>> +                       }
>>> +                       unlock_entry(entry);
>>> +               }
>>> +       }
>>> +
>>> +       return ODP_PKTIO_INVALID;
>>> +}
>>> +
>>> +static int free_pktio_entry(odp_pktio_t id)
>>> +{
>>> +       pktio_entry_t *entry = get_entry(id);
>>> +
>>> +       if (entry == NULL)
>>> +               return -1;
>>> +
>>> +       set_free(entry);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
>>> +                          odp_pktio_params_t *params)
>>> +{
>>> +       odp_pktio_t id;
>>> +       pktio_entry_t *pktio_entry;
>>> +       int res;
>>> +
>>> +       if (params == NULL) {
>>> +               ODP_ERR("Invalid pktio params\n");
>>> +               return ODP_PKTIO_INVALID;
>>> +       }
>>> +
>>> +       switch (params->type) {
>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>> +               ODP_DBG("Allocating socket pktio\n");
>>> +               break;
>>> +#ifdef ODP_HAVE_NETMAP
>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>> +               ODP_DBG("Allocating netmap pktio\n");
>>> +               break;
>>> +#endif
>>> +       case ODP_PKTIO_TYPE_DPDK:
>>> +               ODP_DBG("Allocating dpdk pktio\n");
>>> +               break;
>>> +       default:
>>> +               ODP_ERR("Invalid pktio type: %02x\n", params->type);
>>> +               return ODP_PKTIO_INVALID;
>>> +       }
>>> +
>>> +       id = alloc_lock_pktio_entry(params);
>>> +       if (id == ODP_PKTIO_INVALID) {
>>> +               ODP_ERR("No resources available.\n");
>>> +               return ODP_PKTIO_INVALID;
>>> +       }
>>> +       /* if successful, alloc_pktio_entry() returns with the entry
>>> locked */
>>> +
>>> +       pktio_entry = get_entry(id);
>>> +
>>> +       switch (params->type) {
>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>> +               res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev,
>>> pool);
>>> +               if (res == -1) {
>>> +                       close_pkt_sock(&pktio_entry->s.pkt_sock);
>>> +                       free_pktio_entry(id);
>>> +                       id = ODP_PKTIO_INVALID;
>>> +               }
>>> +               break;
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>> +               res = setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>>> dev,
>>> +                               pool, params->sock_params.fanout);
>>> +               if (res == -1) {
>>> +
>>> close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap);
>>> +                       free_pktio_entry(id);
>>> +                       id = ODP_PKTIO_INVALID;
>>> +               }
>>> +               break;
>>> +#ifdef ODP_HAVE_NETMAP
>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>> +
>>> +               res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev,
>>> +                               pool, &params->nm_params);
>>> +               if (res == -1) {
>>> +                       close_pkt_netmap(&pktio_entry->s.pkt_nm);
>>> +                       free_pktio_entry(id);
>>> +                       id = ODP_PKTIO_INVALID;
>>> +               }
>>> +               break;
>>> +#endif
>>> +       case ODP_PKTIO_TYPE_DPDK:
>>> +               res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev,
>>> pool);
>>> +               if (res == -1) {
>>> +                       close_pkt_dpdk(&pktio_entry->s.pkt_dpdk);
>>> +                       free_pktio_entry(id);
>>> +                       id = ODP_PKTIO_INVALID;
>>> +               }
>>> +               break;
>>> +       default:
>>> +               free_pktio_entry(id);
>>> +               id = ODP_PKTIO_INVALID;
>>> +               ODP_ERR("Invalid pktio type. Please recompile.\n");
>>> +               break;
>>> +       }
>>> +
>>> +       unlock_entry(pktio_entry);
>>> +       return id;
>>> +}
>>> +
>>> +int odp_pktio_close(odp_pktio_t id)
>>> +{
>>> +       pktio_entry_t *entry;
>>> +       int res = -1;
>>> +
>>> +       entry = get_entry(id);
>>> +       if (entry == NULL)
>>> +               return -1;
>>> +
>>> +       lock_entry(entry);
>>> +       if (!is_free(entry)) {
>>> +               switch (entry->s.params.type) {
>>> +               case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>> +               case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>> +                       res  = close_pkt_sock(&entry->s.pkt_sock);
>>> +                       break;
>>> +               case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>> +                       res  =
>>> close_pkt_sock_mmap(&entry->s.pkt_sock_mmap);
>>> +                       break;
>>> +#ifdef ODP_HAVE_NETMAP
>>> +               case ODP_PKTIO_TYPE_NETMAP:
>>> +                       res  = close_pkt_netmap(&entry->s.pkt_nm);
>>> +                       break;
>>> +#endif
>>> +               case ODP_PKTIO_TYPE_DPDK:
>>> +                       res  = close_pkt_dpdk(&entry->s.pkt_dpdk);
>>> +                       break;
>>> +               default:
>>> +                       break;
>>> +               res |= free_pktio_entry(id);
>>> +               }
>>> +       }
>>> +       unlock_entry(entry);
>>> +
>>> +       if (res != 0)
>>> +               return -1;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio)
>>> +{
>>> +       odp_packet_hdr(pkt)->input = pktio;
>>> +}
>>> +
>>> +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt)
>>> +{
>>> +       return odp_packet_hdr(pkt)->input;
>>> +}
>>> +
>>> +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned
>>> len)
>>> +{
>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>> +       int pkts;
>>> +       int i;
>>> +
>>> +       if (pktio_entry == NULL)
>>> +               return -1;
>>> +
>>> +       lock_entry(pktio_entry);
>>> +       switch (pktio_entry->s.params.type) {
>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>> +               pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock,
>>> +                               pkt_table, len);
>>> +               break;
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>> +               pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
>>> +                               pkt_table, len);
>>> +               break;
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>> +               pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>>> +                               pkt_table, len);
>>> +               break;
>>> +#ifdef ODP_HAVE_NETMAP
>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>> +               pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm,
>>> pkt_table, len);
>>> +               break;
>>> +#endif
>>> +       case ODP_PKTIO_TYPE_DPDK:
>>> +               pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk,
>>> pkt_table, len);
>>> +               break;
>>> +       default:
>>> +               pkts = -1;
>>> +               break;
>>> +       }
>>> +
>>> +       unlock_entry(pktio_entry);
>>> +       if (pkts < 0)
>>> +               return pkts;
>>> +
>>> +       for (i = 0; i < pkts; ++i)
>>> +               odp_pktio_set_input(pkt_table[i], id);
>>> +
>>> +       return pkts;
>>> +}
>>> +
>>> +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned
>>> len)
>>> +{
>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>> +       int pkts;
>>> +
>>> +       if (pktio_entry == NULL)
>>> +               return -1;
>>> +
>>> +       lock_entry(pktio_entry);
>>> +       switch (pktio_entry->s.params.type) {
>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>> +               pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock,
>>> +                               pkt_table, len);
>>> +               break;
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>> +               pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
>>> +                               pkt_table, len);
>>> +               break;
>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>> +               pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>>> +                               pkt_table, len);
>>> +               break;
>>> +#ifdef ODP_HAVE_NETMAP
>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>> +               pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm,
>>> +                               pkt_table, len);
>>> +               break;
>>> +#endif
>>> +       case ODP_PKTIO_TYPE_DPDK:
>>> +               pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk,
>>> +                               pkt_table, len);
>>> +               break;
>>> +       default:
>>> +               pkts = -1;
>>> +       }
>>> +       unlock_entry(pktio_entry);
>>> +
>>> +       return pkts;
>>> +}
>>> +
>>> +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue)
>>> +{
>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>> +       queue_entry_t *qentry = queue_to_qentry(queue);
>>> +
>>> +       if (pktio_entry == NULL || qentry == NULL)
>>> +               return -1;
>>> +
>>> +       if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN)
>>> +               return -1;
>>> +
>>> +       lock_entry(pktio_entry);
>>> +       pktio_entry->s.inq_default = queue;
>>> +       unlock_entry(pktio_entry);
>>> +
>>> +       queue_lock(qentry);
>>> +       qentry->s.pktin = id;
>>> +       qentry->s.status = QUEUE_STATUS_SCHED;
>>> +       queue_unlock(qentry);
>>> +
>>> +       odp_schedule_queue(queue, qentry->s.param.sched.prio);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +int odp_pktio_inq_remdef(odp_pktio_t id)
>>> +{
>>> +       return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID);
>>> +}
>>> +
>>> +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
>>> +{
>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>> +
>>> +       if (pktio_entry == NULL)
>>> +               return ODP_QUEUE_INVALID;
>>> +
>>> +       return pktio_entry->s.inq_default;
>>> +}
>>> +
>>> +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
>>> +{
>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>> +
>>> +       if (pktio_entry == NULL)
>>> +               return ODP_QUEUE_INVALID;
>>> +
>>> +       return pktio_entry->s.outq_default;
>>> +}
>>> +
>>> +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
>>> +{
>>> +       odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t)
>>> buf_hdr);
>>> +       int len = 1;
>>> +       int nbr;
>>> +
>>> +       nbr = odp_pktio_send(qentry->s.pktout, &pkt, len);
>>> +       return (nbr == len ? 0 : -1);
>>> +}
>>> +
>>> +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry)
>>> +{
>>> +       (void)qentry;
>>> +       return NULL;
>>> +}
>>> +
>>> +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
>>> +                    int num)
>>> +{
>>> +       odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>>> +       int nbr;
>>> +       int i;
>>> +
>>> +       for (i = 0; i < num; ++i)
>>> +               pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t)
>>> buf_hdr[i]);
>>> +
>>> +       nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num);
>>> +       return (nbr == num ? 0 : -1);
>>> +}
>>> +
>>> +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
>>> +                    int num)
>>> +{
>>> +       (void)qentry;
>>> +       (void)buf_hdr;
>>> +       (void)num;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
>>> +{
>>> +       /* Use default action */
>>> +       return queue_enq(qentry, buf_hdr);
>>> +}
>>> +
>>> +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
>>> +{
>>> +       odp_buffer_hdr_t *buf_hdr;
>>> +
>>> +       buf_hdr = queue_deq(qentry);
>>> +
>>> +       if (buf_hdr == NULL) {
>>> +               odp_packet_t pkt;
>>> +               odp_buffer_t buf;
>>> +               odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>>> +               odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
>>> +               int pkts, i, j;
>>> +
>>> +               pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
>>> +                                     QUEUE_MULTI_MAX);
>>> +
>>> +               if (pkts > 0) {
>>> +                       pkt = pkt_tbl[0];
>>> +                       buf = odp_buffer_from_packet(pkt);
>>> +                       buf_hdr = odp_buf_to_hdr(buf);
>>> +
>>> +                       for (i = 1, j = 0; i < pkts; ++i) {
>>> +                               buf = odp_buffer_from_packet(pkt_tbl[i]);
>>> +                               tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf);
>>> +                       }
>>> +                       queue_enq_multi(qentry, tmp_hdr_tbl, j);
>>> +               }
>>> +       }
>>> +
>>> +       return buf_hdr;
>>> +}
>>> +
>>> +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
>>> int num)
>>> +{
>>> +       /* Use default action */
>>> +       return queue_enq_multi(qentry, buf_hdr, num);
>>> +}
>>> +
>>> +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
>>> int num)
>>> +{
>>> +       int nbr;
>>> +
>>> +       nbr = queue_deq_multi(qentry, buf_hdr, num);
>>> +
>>> +       if (nbr < num) {
>>> +               odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>>> +               odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
>>> +               odp_buffer_t buf;
>>> +               int pkts, i;
>>> +
>>> +               pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
>>> +                                     QUEUE_MULTI_MAX);
>>> +               if (pkts > 0) {
>>> +                       for (i = 0; i < pkts; ++i) {
>>> +                               buf = odp_buffer_from_packet(pkt_tbl[i]);
>>> +                               tmp_hdr_tbl[i] = odp_buf_to_hdr(buf);
>>> +                       }
>>> +                       queue_enq_multi(qentry, tmp_hdr_tbl, pkts);
>>> +               }
>>> +       }
>>> +
>>> +       return nbr;
>>> +}
>>> diff --git a/platform/linux-dpdk/source/odp_queue.c
>>> b/platform/linux-dpdk/source/odp_queue.c
>>> new file mode 100644
>>> index 0000000..554b8ea
>>> --- /dev/null
>>> +++ b/platform/linux-dpdk/source/odp_queue.c
>>> @@ -0,0 +1,435 @@
>>> +/* Copyright (c) 2013, Linaro Limited
>>> + * All rights reserved.
>>> + *
>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>> + */
>>> +
>>> +#include <odp_queue.h>
>>> +#include <odp_queue_internal.h>
>>> +#include <odp_std_types.h>
>>> +#include <odp_align.h>
>>> +#include <odp_buffer.h>
>>> +#include <odp_buffer_internal.h>
>>> +#include <odp_buffer_pool_internal.h>
>>> +#include <odp_internal.h>
>>> +#include <odp_shared_memory.h>
>>> +#include <odp_schedule_internal.h>
>>> +#include <odp_config.h>
>>> +#include <odp_packet_io_internal.h>
>>> +#include <odp_packet_io_queue.h>
>>> +#include <odp_debug.h>
>>> +#include <odp_hints.h>
>>> +
>>> +#ifdef USE_TICKETLOCK
>>> +#include <odp_ticketlock.h>
>>> +#define LOCK(a)      odp_ticketlock_lock(a)
>>> +#define UNLOCK(a)    odp_ticketlock_unlock(a)
>>> +#define LOCK_INIT(a) odp_ticketlock_init(a)
>>> +#else
>>> +#include <odp_spinlock.h>
>>> +#define LOCK(a)      odp_spinlock_lock(a)
>>> +#define UNLOCK(a)    odp_spinlock_unlock(a)
>>> +#define LOCK_INIT(a) odp_spinlock_init(a)
>>> +#endif
>>> +
>>> +#include <string.h>
>>> +
>>> +
>>> +typedef struct queue_table_t {
>>> +       queue_entry_t  queue[ODP_CONFIG_QUEUES];
>>> +} queue_table_t;
>>> +
>>> +static queue_table_t *queue_tbl;
>>> +
>>> +
>>> +queue_entry_t *get_qentry(uint32_t queue_id)
>>> +{
>>> +       return &queue_tbl->queue[queue_id];
>>> +}
>>> +
>>> +static void queue_init(queue_entry_t *queue, const char *name,
>>> +                      odp_queue_type_t type, odp_queue_param_t *param)
>>> +{
>>> +       strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1);
>>> +       queue->s.type = type;
>>> +
>>> +       if (param) {
>>> +               memcpy(&queue->s.param, param,
>>> sizeof(odp_queue_param_t));
>>> +       } else {
>>> +               /* Defaults */
>>> +               memset(&queue->s.param, 0, sizeof(odp_queue_param_t));
>>> +               queue->s.param.sched.prio  = ODP_SCHED_PRIO_DEFAULT;
>>> +               queue->s.param.sched.sync  = ODP_SCHED_SYNC_DEFAULT;
>>> +               queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT;
>>> +       }
>>> +
>>> +       switch (type) {
>>> +       case ODP_QUEUE_TYPE_PKTIN:
>>> +               queue->s.enqueue = pktin_enqueue;
>>> +               queue->s.dequeue = pktin_dequeue;
>>> +               queue->s.enqueue_multi = pktin_enq_multi;
>>> +               queue->s.dequeue_multi = pktin_deq_multi;
>>> +               break;
>>> +       case ODP_QUEUE_TYPE_PKTOUT:
>>> +               queue->s.enqueue = pktout_enqueue;
>>> +               queue->s.dequeue = pktout_dequeue;
>>> +               queue->s.enqueue_multi = pktout_enq_multi;
>>> +               queue->s.dequeue_multi = pktout_deq_multi;
>>> +               break;
>>> +       default:
>>> +               queue->s.enqueue = queue_enq;
>>> +               queue->s.dequeue = queue_deq;
>>> +               queue->s.enqueue_multi = queue_enq_multi;
>>> +               queue->s.dequeue_multi = queue_deq_multi;
>>> +               break;
>>> +       }
>>> +
>>> +       queue->s.head = NULL;
>>> +       queue->s.tail = NULL;
>>> +       queue->s.sched_buf = ODP_BUFFER_INVALID;
>>> +}
>>> +
>>> +
>>> +int odp_queue_init_global(void)
>>> +{
>>> +       uint32_t i;
>>> +
>>> +       ODP_DBG("Queue init ... ");
>>> +
>>> +       queue_tbl = odp_shm_reserve("odp_queues",
>>> +                                   sizeof(queue_table_t),
>>> +                                   sizeof(queue_entry_t));
>>> +
>>> +       if (queue_tbl == NULL)
>>> +               return -1;
>>> +
>>> +       memset(queue_tbl, 0, sizeof(queue_table_t));
>>> +
>>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>>> +               /* init locks */
>>> +               queue_entry_t *queue = get_qentry(i);
>>> +               LOCK_INIT(&queue->s.lock);
>>> +               queue->s.handle = queue_from_id(i);
>>> +       }
>>> +
>>> +       ODP_DBG("done\n");
>>> +       ODP_DBG("Queue init global\n");
>>> +       ODP_DBG("  struct queue_entry_s size %zu\n",
>>> +               sizeof(struct queue_entry_s));
>>> +       ODP_DBG("  queue_entry_t size        %zu\n",
>>> +               sizeof(queue_entry_t));
>>> +       ODP_DBG("\n");
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +odp_queue_type_t odp_queue_type(odp_queue_t handle)
>>> +{
>>> +       queue_entry_t *queue;
>>> +
>>> +       queue = queue_to_qentry(handle);
>>> +
>>> +       return queue->s.type;
>>> +}
>>> +
>>> +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle)
>>> +{
>>> +       queue_entry_t *queue;
>>> +
>>> +       queue = queue_to_qentry(handle);
>>> +
>>> +       return queue->s.param.sched.sync;
>>> +}
>>> +
>>> +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
>>> +                            odp_queue_param_t *param)
>>> +{
>>> +       uint32_t i;
>>> +       queue_entry_t *queue;
>>> +       odp_queue_t handle = ODP_QUEUE_INVALID;
>>> +
>>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>>> +               queue = &queue_tbl->queue[i];
>>> +
>>> +               if (queue->s.status != QUEUE_STATUS_FREE)
>>> +                       continue;
>>> +
>>> +               LOCK(&queue->s.lock);
>>> +               if (queue->s.status == QUEUE_STATUS_FREE) {
>>> +                       queue_init(queue, name, type, param);
>>> +
>>> +                       if (type == ODP_QUEUE_TYPE_SCHED ||
>>> +                           type == ODP_QUEUE_TYPE_PKTIN)
>>> +                               queue->s.status = QUEUE_STATUS_NOTSCHED;
>>> +                       else
>>> +                               queue->s.status = QUEUE_STATUS_READY;
>>> +
>>> +                       handle = queue->s.handle;
>>> +                       UNLOCK(&queue->s.lock);
>>> +                       break;
>>> +               }
>>> +               UNLOCK(&queue->s.lock);
>>> +       }
>>> +
>>> +       if (handle != ODP_QUEUE_INVALID &&
>>> +           (type == ODP_QUEUE_TYPE_SCHED || type ==
>>> ODP_QUEUE_TYPE_PKTIN)) {
>>> +               odp_buffer_t buf;
>>> +
>>> +               buf = odp_schedule_buffer_alloc(handle);
>>> +               if (buf == ODP_BUFFER_INVALID) {
>>> +                       ODP_ERR("queue_init: sched buf alloc failed\n");
>>> +                       return ODP_QUEUE_INVALID;
>>> +               }
>>> +
>>> +               queue->s.sched_buf = buf;
>>> +               odp_schedule_mask_set(handle, queue->s.param.sched.prio);
>>> +       }
>>> +
>>> +       return handle;
>>> +}
>>> +
>>> +
>>> +odp_buffer_t queue_sched_buf(odp_queue_t handle)
>>> +{
>>> +       queue_entry_t *queue;
>>> +       queue = queue_to_qentry(handle);
>>> +
>>> +       return queue->s.sched_buf;
>>> +}
>>> +
>>> +
>>> +int queue_sched_atomic(odp_queue_t handle)
>>> +{
>>> +       queue_entry_t *queue;
>>> +       queue = queue_to_qentry(handle);
>>> +
>>> +       return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC;
>>> +}
>>> +
>>> +
>>> +odp_queue_t odp_queue_lookup(const char *name)
>>> +{
>>> +       uint32_t i;
>>> +
>>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>>> +               queue_entry_t *queue = &queue_tbl->queue[i];
>>> +
>>> +               if (queue->s.status == QUEUE_STATUS_FREE)
>>> +                       continue;
>>> +
>>> +               LOCK(&queue->s.lock);
>>> +               if (strcmp(name, queue->s.name) == 0) {
>>> +                       /* found it */
>>> +                       UNLOCK(&queue->s.lock);
>>> +                       return queue->s.handle;
>>> +               }
>>> +               UNLOCK(&queue->s.lock);
>>> +       }
>>> +
>>> +       return ODP_QUEUE_INVALID;
>>> +}
>>> +
>>> +
>>> +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
>>> +{
>>> +       int sched = 0;
>>> +
>>> +       LOCK(&queue->s.lock);
>>> +       if (queue->s.head == NULL) {
>>> +               /* Empty queue */
>>> +               queue->s.head = buf_hdr;
>>> +               queue->s.tail = buf_hdr;
>>> +               buf_hdr->pkt.next = NULL;
>>> +       } else {
>>> +               queue->s.tail->pkt.next = buf_hdr;
>>> +               queue->s.tail = buf_hdr;
>>> +               buf_hdr->pkt.next = NULL;
>>> +       }
>>> +
>>> +       if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
>>> +               queue->s.status = QUEUE_STATUS_SCHED;
>>> +               sched = 1; /* retval: schedule queue */
>>> +       }
>>> +       UNLOCK(&queue->s.lock);
>>> +
>>> +       /* Add queue to scheduling */
>>> +       if (sched == 1)
>>> +               odp_schedule_queue(queue->s.handle,
>>> queue->s.param.sched.prio);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +
>>> +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
>>> int num)
>>> +{
>>> +       int sched = 0;
>>> +       int i;
>>> +       odp_buffer_hdr_t *tail;
>>> +
>>> +       for (i = 0; i < num - 1; i++)
>>> +               buf_hdr[i]->pkt.next = buf_hdr[i+1];
>>> +
>>> +       tail = buf_hdr[num-1];
>>> +       buf_hdr[num-1]->pkt.next = NULL;
>>> +
>>> +       LOCK(&queue->s.lock);
>>> +       /* Empty queue */
>>> +       if (queue->s.head == NULL)
>>> +               queue->s.head = buf_hdr[0];
>>> +       else
>>> +               queue->s.tail->pkt.next = buf_hdr[0];
>>> +
>>> +       queue->s.tail = tail;
>>> +
>>> +       if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
>>> +               queue->s.status = QUEUE_STATUS_SCHED;
>>> +               sched = 1; /* retval: schedule queue */
>>> +       }
>>> +       UNLOCK(&queue->s.lock);
>>> +
>>> +       /* Add queue to scheduling */
>>> +       if (sched == 1)
>>> +               odp_schedule_queue(queue->s.handle,
>>> queue->s.param.sched.prio);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +
>>> +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int num)
>>> +{
>>> +       odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
>>> +       queue_entry_t *queue;
>>> +       int i;
>>> +
>>> +       if (num > QUEUE_MULTI_MAX)
>>> +               num = QUEUE_MULTI_MAX;
>>> +
>>> +       queue = queue_to_qentry(handle);
>>> +
>>> +       for (i = 0; i < num; i++)
>>> +               buf_hdr[i] = odp_buf_to_hdr(buf[i]);
>>> +
>>> +       return queue->s.enqueue_multi(queue, buf_hdr, num);
>>> +}
>>> +
>>> +
>>> +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf)
>>> +{
>>> +       odp_buffer_hdr_t *buf_hdr;
>>> +       queue_entry_t *queue;
>>> +
>>> +       queue   = queue_to_qentry(handle);
>>> +       buf_hdr = odp_buf_to_hdr(buf);
>>> +
>>> +       return queue->s.enqueue(queue, buf_hdr);
>>> +}
>>> +
>>> +
>>> +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
>>> +{
>>> +       odp_buffer_hdr_t *buf_hdr = NULL;
>>> +
>>> +       LOCK(&queue->s.lock);
>>> +
>>> +       if (queue->s.head == NULL) {
>>> +               /* Already empty queue */
>>> +               if (queue->s.status == QUEUE_STATUS_SCHED &&
>>> +                   queue->s.type != ODP_QUEUE_TYPE_PKTIN)
>>> +                       queue->s.status = QUEUE_STATUS_NOTSCHED;
>>> +       } else {
>>> +               buf_hdr       = queue->s.head;
>>> +               queue->s.head = buf_hdr->pkt.next;
>>> +               buf_hdr->pkt.next = NULL;
>>> +
>>> +               if (queue->s.head == NULL) {
>>> +                       /* Queue is now empty */
>>> +                       queue->s.tail = NULL;
>>> +               }
>>> +       }
>>> +
>>> +       UNLOCK(&queue->s.lock);
>>> +
>>> +       return buf_hdr;
>>> +}
>>> +
>>> +
>>> +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
>>> int num)
>>> +{
>>> +       int i = 0;
>>> +
>>> +       LOCK(&queue->s.lock);
>>> +
>>> +       if (queue->s.head == NULL) {
>>> +               /* Already empty queue */
>>> +               if (queue->s.status == QUEUE_STATUS_SCHED &&
>>> +                   queue->s.type != ODP_QUEUE_TYPE_PKTIN)
>>> +                       queue->s.status = QUEUE_STATUS_NOTSCHED;
>>> +       } else {
>>> +               odp_buffer_hdr_t *hdr = queue->s.head;
>>> +
>>> +               for (; i < num && hdr; i++) {
>>> +                       buf_hdr[i]       = hdr;
>>> +                       /* odp_prefetch(hdr->addr); */
>>> +                       hdr              = hdr->pkt.next;
>>> +                       buf_hdr[i]->pkt.next = NULL;
>>> +               }
>>> +
>>> +               queue->s.head = hdr;
>>> +
>>> +               if (hdr == NULL) {
>>> +                       /* Queue is now empty */
>>> +                       queue->s.tail = NULL;
>>> +               }
>>> +       }
>>> +
>>> +       UNLOCK(&queue->s.lock);
>>> +
>>> +       return i;
>>> +}
>>> +
>>> +
>>> +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int num)
>>> +{
>>> +       queue_entry_t *queue;
>>> +       odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
>>> +       int i, ret;
>>> +
>>> +       if (num > QUEUE_MULTI_MAX)
>>> +               num = QUEUE_MULTI_MAX;
>>> +
>>> +       queue = queue_to_qentry(handle);
>>> +
>>> +       ret = queue->s.dequeue_multi(queue, buf_hdr, num);
>>> +
>>> +       for (i = 0; i < ret; i++)
>>> +               buf[i] = (odp_buffer_t) buf_hdr[i];
>>> +
>>> +       return ret;
>>> +}
>>> +
>>> +
>>> +odp_buffer_t odp_queue_deq(odp_queue_t handle)
>>> +{
>>> +       queue_entry_t *queue;
>>> +       odp_buffer_hdr_t *buf_hdr;
>>> +
>>> +       queue   = queue_to_qentry(handle);
>>> +       buf_hdr = queue->s.dequeue(queue);
>>> +
>>> +       if (buf_hdr)
>>> +               return (odp_buffer_t) buf_hdr;
>>> +
>>> +       return ODP_BUFFER_INVALID;
>>> +}
>>> +
>>> +
>>> +void queue_lock(queue_entry_t *queue)
>>> +{
>>> +       LOCK(&queue->s.lock);
>>> +}
>>> +
>>> +
>>> +void queue_unlock(queue_entry_t *queue)
>>> +{
>>> +       UNLOCK(&queue->s.lock);
>>> +}
>>> --
>>> 1.9.1
>>>
>>>
>>> _______________________________________________
>>> lng-odp mailing list
>>> lng-odp@lists.linaro.org
>>> http://lists.linaro.org/mailman/listinfo/lng-odp
>>>
>>
>>
>>
>> --
>> *Mike Holmes*
>> Linaro Technical Manager / Lead
>> LNG - ODP
>>
>
>
Venkatesh Vivekanandan July 15, 2014, 9:48 a.m. UTC | #4
On 12 July 2014 17:31, Mike Holmes <mike.holmes@linaro.org> wrote:

>
>
>
> On 12 July 2014 04:20, Venkatesh Vivekanandan <
> venkatesh.vivekanandan@linaro.org> wrote:
>
>>
>>
>>
>> On 12 July 2014 01:14, Mike Holmes <mike.holmes@linaro.org> wrote:
>>
>>> Adds whitespace errors when applied.
>>>
>>
>> Ran checkpatch.pl before submitting the patch. Please point to the
>> error/warning if any.
>>
> mike@fedora1:~/git/odp$ git am
> ~/incoming/lng-odp_PATCH_1-2_initial_odp_dpdk.mbox
> Applying: initial odp dpdk
> error: platform/linux-dpdk/Makefile: already exists in working directory
> /home/mike/git/odp/.git/rebase-apply/patch:216: new blank line at EOF.
> +
> /home/mike/git/odp/.git/rebase-apply/patch:792: new blank line at EOF.
> +
> /home/mike/git/odp/.git/rebase-apply/patch:988: new blank line at EOF.
> +
> /home/mike/git/odp/.git/rebase-apply/patch:1134: new blank line at EOF.
> +
> /home/mike/git/odp/.git/rebase-apply/patch:1192: new blank line at EOF.
> +
> Patch failed at 0001 initial odp dpdk
> The copy of the patch that failed is found in:
>    /home/mike/git/odp/.git/rebase-apply/patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
>

There are empty lines at end of the file and somehow checkpatch.pl didn't
catch, but git am does. I will fix them, add a README and send out a patch
v2


>
>
>>
>>
>>> Also needs a README like the one in linux-keystone to indicate such
>>> things as setting ./configure --with-platform=linux-dpdk
>>> And how to then ensure  dpdk is installed to resolve things like
>>>
>>
>> Forgot to mention that prerequisite is, dpdk should be checked out and
>> compiled. I will probably add it in a README and send out a patch for that.
>>
>>
>>> /usr/include/stdc-predef.h:59:1: fatal error:
>>> ../../../dpdk/build/include/rte_config.h: No such file or directory
>>>
>>
>>>
>>> On 11 July 2014 14:35, <venkatesh.vivekanandan@linaro.org> wrote:
>>>
>>>> From: Vincent Hsu <vincent.hsu@linaro.org>
>>>>
>>>> Signed-off-by: Venkatesh Vivekanandan <
>>>> venkatesh.vivekanandan@linaro.org>
>>>> ---
>>>>  platform/linux-dpdk/Makefile                       | 158 ++++++
>>>>  platform/linux-dpdk/Makefile.inc                   |   7 +
>>>>  platform/linux-dpdk/include/api/odp_buffer.h       | 101 ++++
>>>>  platform/linux-dpdk/include/api/odp_buffer_pool.h  |  99 ++++
>>>>  platform/linux-dpdk/include/api/odp_packet.h       | 228 +++++++++
>>>>  platform/linux-dpdk/include/api/odp_pktio_types.h  |  45 ++
>>>>  platform/linux-dpdk/include/odp_buffer_internal.h  |  79 +++
>>>>  .../linux-dpdk/include/odp_buffer_pool_internal.h  |  90 ++++
>>>>  platform/linux-dpdk/include/odp_packet_dpdk.h      |  88 ++++
>>>>  platform/linux-dpdk/include/odp_packet_internal.h  | 140 +++++
>>>>  .../linux-dpdk/include/odp_packet_io_internal.h    |  52 ++
>>>>  platform/linux-dpdk/source/odp_buffer.c            | 102 ++++
>>>>  platform/linux-dpdk/source/odp_buffer_pool.c       | 156 ++++++
>>>>  platform/linux-dpdk/source/odp_init.c              | 113 +++++
>>>>  platform/linux-dpdk/source/odp_packet.c            | 374 ++++++++++++++
>>>>  platform/linux-dpdk/source/odp_packet_dpdk.c       | 177 +++++++
>>>>  platform/linux-dpdk/source/odp_packet_io.c         | 561
>>>> +++++++++++++++++++++
>>>>  platform/linux-dpdk/source/odp_queue.c             | 435
>>>> ++++++++++++++++
>>>>  18 files changed, 3005 insertions(+)
>>>>  create mode 100644 platform/linux-dpdk/Makefile
>>>>  create mode 100644 platform/linux-dpdk/Makefile.inc
>>>>  create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h
>>>>  create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h
>>>>  create mode 100644 platform/linux-dpdk/include/api/odp_packet.h
>>>>  create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h
>>>>  create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h
>>>>  create mode 100644
>>>> platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>>>  create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h
>>>>  create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h
>>>>  create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h
>>>>  create mode 100644 platform/linux-dpdk/source/odp_buffer.c
>>>>  create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c
>>>>  create mode 100644 platform/linux-dpdk/source/odp_init.c
>>>>  create mode 100644 platform/linux-dpdk/source/odp_packet.c
>>>>  create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c
>>>>  create mode 100644 platform/linux-dpdk/source/odp_packet_io.c
>>>>  create mode 100644 platform/linux-dpdk/source/odp_queue.c
>>>>
>>>> diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile
>>>> new file mode 100644
>>>> index 0000000..bf8d0b3
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/Makefile
>>>> @@ -0,0 +1,158 @@
>>>> +## Copyright (c) 2013, Linaro Limited
>>>> +## All rights reserved.
>>>> +##
>>>> +## Redistribution and use in source and binary forms, with or without
>>>> +## modification, are permitted provided that the following conditions
>>>> are met:
>>>> +##
>>>> +##    * Redistributions of source code must retain the above copyright
>>>> notice, this
>>>> +##      list of conditions and the following disclaimer.
>>>> +##
>>>> +##    * Redistributions in binary form must reproduce the above
>>>> copyright notice, this
>>>> +##      list of conditions and the following disclaimer in the
>>>> documentation and/or
>>>> +##      other materials provided with the distribution.
>>>> +##
>>>> +##    * Neither the name of Linaro Limited nor the names of its
>>>> contributors may be
>>>> +##      used to endorse or promote products derived from this software
>>>> without specific
>>>> +##      prior written permission.
>>>> +##
>>>> +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>>>> "AS IS" AND
>>>> +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
>>>> THE IMPLIED
>>>> +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
>>>> ARE
>>>> +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
>>>> BE LIABLE
>>>> +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
>>>> CONSEQUENTIAL
>>>> +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
>>>> GOODS OR
>>>> +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
>>>> HOWEVER
>>>> +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
>>>> LIABILITY,
>>>> +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>>>> OF THE USE
>>>> +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>>>> +
>>>> +.DEFAULT_GOAL := libs
>>>> +
>>>> +ODP_ROOT = ../..
>>>> +LIB_DIR  = ./lib
>>>> +DOC_DIR  = ./doc
>>>> +
>>>> +LINUX_GENERIC_DIR = ../linux-generic
>>>> +
>>>> +RTE_SDK    ?= $(abspath $(ODP_ROOT)/../dpdk)
>>>> +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build)
>>>> +RTE_LIB    ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a)
>>>> +
>>>> +PLAT_CFLAGS  = -include $(RTE_OUTPUT)/include/rte_config.h
>>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include
>>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch
>>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env
>>>> +PLAT_CFLAGS += -msse4.2
>>>> +
>>>> +EXTRA_CFLAGS += $(PLAT_CFLAGS)
>>>> +EXTRA_CFLAGS += -I./include
>>>> +EXTRA_CFLAGS += -I./include/api
>>>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include
>>>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api
>>>> +EXTRA_CFLAGS += -I$(ODP_ROOT)/include
>>>> +
>>>> +include $(ODP_ROOT)/Makefile.inc
>>>> +STATIC_LIB = ./lib/libodp.a
>>>> +
>>>> +#
>>>> +# Object files
>>>> +#
>>>> +OBJS     =
>>>> +OBJS    += $(OBJ_DIR)/odp_barrier.o
>>>> +OBJS    += $(OBJ_DIR)/odp_buffer.o
>>>> +OBJS    += $(OBJ_DIR)/odp_buffer_pool.o
>>>> +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
>>>> +OBJS    += $(OBJ_DIR)/odp_schedule.o
>>>> +OBJS    += $(OBJ_DIR)/odp_shared_memory.o
>>>> +OBJS    += $(OBJ_DIR)/odp_spinlock.o
>>>> +OBJS    += $(OBJ_DIR)/odp_system_info.o
>>>> +OBJS    += $(OBJ_DIR)/odp_thread.o
>>>> +OBJS    += $(OBJ_DIR)/odp_ticketlock.o
>>>> +OBJS    += $(OBJ_DIR)/odp_time.o
>>>> +OBJS    += $(OBJ_DIR)/odp_timer.o
>>>> +OBJS    += $(OBJ_DIR)/odp_ring.o
>>>> +OBJS    += $(OBJ_DIR)/odp_rwlock.o
>>>> +OBJS    += $(OBJ_DIR)/odp_packet_dpdk.o
>>>> +
>>>> +DEPS     = $(OBJS:.o=.d)
>>>> +
>>>> +.PHONY: all
>>>> +all: libs docs
>>>> +
>>>> +-include $(DEPS)
>>>> +
>>>> +#$(OBJ_DIR):
>>>> +#      $(MKDIR) $(OBJ_DIR)
>>>> +
>>>> +$(LIB_DIR):
>>>> +       $(MKDIR) $(LIB_DIR)
>>>> +
>>>> +$(DOC_DIR):
>>>> +       $(MKDIR) $(DOC_DIR)/html
>>>> +       $(MKDIR) $(DOC_DIR)/latex
>>>> +
>>>> +#
>>>> +# Compile rules
>>>> +#
>>>> +vpath %.c source:$(LINUX_GENERIC_DIR)/source
>>>> +
>>>> +$(OBJ_DIR)/%.o: %.c
>>>> +       $(ECHO) "  CC    $<"
>>>> +       $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $<
>>>> +
>>>> +#
>>>> +# Lib rule
>>>> +#
>>>> +$(OBJ_DIR)/libodp.o: $(OBJS)
>>>> +       $(ECHO) "  LD    $@"
>>>> +       $(LD) -r -o $@ $(OBJS) $(RTE_LIB)
>>>> +
>>>> +$(STATIC_LIB): $(OBJ_DIR)/libodp.o
>>>> +       $(ECHO) "  AR    $@"
>>>> +       $(AR) -cr $@ $(OBJ_DIR)/libodp.o
>>>> +
>>>> +
>>>> +clean:
>>>> +       $(RMDIR) $(OBJ_DIR)
>>>> +       $(RMDIR) $(LIB_DIR)
>>>> +       $(RMDIR) $(DOC_DIR)
>>>> +       $(RM) Doxyfile
>>>> +
>>>> +Doxyfile: Doxyfile.in
>>>> +       doxygen -u - < $< > $@
>>>> +
>>>> +.PHONY: docs
>>>> +docs: $(DOC_DIR) Doxyfile ./include/odp*.h
>>>> +       doxygen
>>>> +
>>>> +.PHONY: docs_install
>>>> +docs_install: docs
>>>> +       $(COPY) doc $(DESTDIR)
>>>> +
>>>> +.PHONY: pdf
>>>> +pdf: docs
>>>> +       make --directory doc/latex refman.pdf 1> /dev/null
>>>> +
>>>> +.PHONY: libs
>>>> +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB)
>>>> +
>>>> +.PHONY: lib_install
>>>> +lib_install: libs
>>>> +       install -d $(DESTDIR)/lib
>>>> +       install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/
>>>> +
>>>> +.PHONY: headers_install
>>>> +headers_install: libs
>>>> +       $(ECHO) Installing headers to $(DESTDIR)/include
>>>> +       $(COPY) $(ODP_ROOT)/include $(DESTDIR)
>>>> +       $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/
>>>> +       $(COPY) include/api/* $(DESTDIR)/include/
>>>> +
>>>> +install: lib_install headers_install
>>>> diff --git a/platform/linux-dpdk/Makefile.inc
>>>> b/platform/linux-dpdk/Makefile.inc
>>>> new file mode 100644
>>>> index 0000000..fe7679b
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/Makefile.inc
>>>> @@ -0,0 +1,7 @@
>>>> +# Copyright (c) 2013, Linaro Limited
>>>> +# All rights reserved.
>>>> +#
>>>> +# SPDX-License-Identifier:     BSD-3-Clause
>>>> +
>>>> +STD_LIBS += -ldl
>>>> +
>>>> diff --git a/platform/linux-dpdk/include/api/odp_buffer.h
>>>> b/platform/linux-dpdk/include/api/odp_buffer.h
>>>> new file mode 100644
>>>> index 0000000..286d9e6
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/api/odp_buffer.h
>>>> @@ -0,0 +1,101 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +
>>>> +/**
>>>> + * @file
>>>> + *
>>>> + * ODP buffer descriptor
>>>> + */
>>>> +
>>>> +#ifndef ODP_BUFFER_H_
>>>> +#define ODP_BUFFER_H_
>>>> +
>>>> +#ifdef __cplusplus
>>>> +extern "C" {
>>>> +#endif
>>>> +
>>>> +
>>>> +
>>>> +#include <odp_std_types.h>
>>>> +
>>>> +
>>>> +
>>>> +
>>>> +
>>>> +/**
>>>> + * ODP buffer
>>>> + */
>>>> +typedef unsigned long odp_buffer_t;
>>>> +
>>>> +
>>>> +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */
>>>> +
>>>> +
>>>> +/**
>>>> + * Buffer start address
>>>> + *
>>>> + * @param buf      Buffer handle
>>>> + *
>>>> + * @return Buffer start address
>>>> + */
>>>> +void *odp_buffer_addr(odp_buffer_t buf);
>>>> +
>>>> +/**
>>>> + * Buffer maximum data size
>>>> + *
>>>> + * @param buf      Buffer handle
>>>> + *
>>>> + * @return Buffer maximum data size
>>>> + */
>>>> +size_t odp_buffer_size(odp_buffer_t buf);
>>>> +
>>>> +/**
>>>> + * Buffer type
>>>> + *
>>>> + * @param buf      Buffer handle
>>>> + *
>>>> + * @return Buffer type
>>>> + */
>>>> +int odp_buffer_type(odp_buffer_t buf);
>>>> +
>>>> +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */
>>>> +#define ODP_BUFFER_TYPE_RAW       0  /**< Raw buffer */
>>>> +#define ODP_BUFFER_TYPE_PACKET    1  /**< Packet buffer */
>>>> +#define ODP_BUFFER_TYPE_TIMER     2  /**< Timer buffer */
>>>> +
>>>> +/**
>>>> + * Tests if buffer is part of a scatter/gather list
>>>> + *
>>>> + * @param buf      Buffer handle
>>>> + *
>>>> + * @return 1 if belongs to a scatter list, otherwise 0
>>>> + */
>>>> +int odp_buffer_is_scatter(odp_buffer_t buf);
>>>> +
>>>> +/**
>>>> + * Tests if buffer is valid
>>>> + *
>>>> + * @param buf      Buffer handle
>>>> + *
>>>> + * @return 1 if valid, otherwise 0
>>>> + */
>>>> +int odp_buffer_is_valid(odp_buffer_t buf);
>>>> +
>>>> +/**
>>>> + * Print buffer metadata to STDOUT
>>>> + *
>>>> + * @param buf      Buffer handle
>>>> + *
>>>> + */
>>>> +void odp_buffer_print(odp_buffer_t buf);
>>>> +
>>>> +
>>>> +#ifdef __cplusplus
>>>> +}
>>>> +#endif
>>>> +
>>>> +#endif
>>>> diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h
>>>> b/platform/linux-dpdk/include/api/odp_buffer_pool.h
>>>> new file mode 100644
>>>> index 0000000..4b75cf5
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h
>>>> @@ -0,0 +1,99 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +
>>>> +/**
>>>> + * @file
>>>> + *
>>>> + * ODP buffer pool
>>>> + */
>>>> +
>>>> +#ifndef ODP_BUFFER_POOL_H_
>>>> +#define ODP_BUFFER_POOL_H_
>>>> +
>>>> +#ifdef __cplusplus
>>>> +extern "C" {
>>>> +#endif
>>>> +
>>>> +
>>>> +
>>>> +#include <odp_std_types.h>
>>>> +#include <odp_buffer.h>
>>>> +
>>>> +/** Maximum queue name lenght in chars */
>>>> +#define ODP_BUFFER_POOL_NAME_LEN  32
>>>> +
>>>> +/** Invalid buffer pool */
>>>> +#define ODP_BUFFER_POOL_INVALID  (0xffffffff)
>>>> +
>>>> +/** ODP buffer pool */
>>>> +typedef unsigned long odp_buffer_pool_t;
>>>> +
>>>> +
>>>> +/**
>>>> + * Create a buffer pool
>>>> + *
>>>> + * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1
>>>> chars)
>>>> + * @param base_addr Pool base address
>>>> + * @param size      Pool size in bytes
>>>> + * @param buf_size  Buffer size in bytes
>>>> + * @param buf_align Minimum buffer alignment
>>>> + * @param buf_type  Buffer type
>>>> + *
>>>> + * @return Buffer pool handle
>>>> + */
>>>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name,
>>>> +                                        void *base_addr, uint64_t size,
>>>> +                                        size_t buf_size, size_t
>>>> buf_align,
>>>> +                                        int buf_type);
>>>> +
>>>> +
>>>> +/**
>>>> + * Find a buffer pool by name
>>>> + *
>>>> + * @param name      Name of the pool
>>>> + *
>>>> + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
>>>> + */
>>>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name);
>>>> +
>>>> +
>>>> +/**
>>>> + * Print buffer pool info
>>>> + *
>>>> + * @param pool      Pool handle
>>>> + *
>>>> + */
>>>> +void odp_buffer_pool_print(odp_buffer_pool_t pool);
>>>> +
>>>> +
>>>> +
>>>> +/**
>>>> + * Buffer alloc
>>>> + *
>>>> + * @param pool      Pool handle
>>>> + *
>>>> + * @return Buffer handle or ODP_BUFFER_INVALID
>>>> + */
>>>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool);
>>>> +
>>>> +
>>>> +/**
>>>> + * Buffer free
>>>> + *
>>>> + * @param buf       Buffer handle
>>>> + *
>>>> + */
>>>> +void odp_buffer_free(odp_buffer_t buf);
>>>> +
>>>> +
>>>> +
>>>> +
>>>> +#ifdef __cplusplus
>>>> +}
>>>> +#endif
>>>> +
>>>> +#endif
>>>> diff --git a/platform/linux-dpdk/include/api/odp_packet.h
>>>> b/platform/linux-dpdk/include/api/odp_packet.h
>>>> new file mode 100644
>>>> index 0000000..bdb3417
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/api/odp_packet.h
>>>> @@ -0,0 +1,228 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +
>>>> +/**
>>>> + * @file
>>>> + *
>>>> + * ODP packet descriptor
>>>> + */
>>>> +
>>>> +#ifndef ODP_PACKET_H_
>>>> +#define ODP_PACKET_H_
>>>> +
>>>> +#ifdef __cplusplus
>>>> +extern "C" {
>>>> +#endif
>>>> +
>>>> +#include <odp_buffer.h>
>>>> +
>>>> +
>>>> +/**
>>>> + * ODP packet descriptor
>>>> + */
>>>> +typedef unsigned long odp_packet_t;
>>>> +
>>>> +
>>>> +/** Invalid packet */
>>>> +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID
>>>> +
>>>> +/** Invalid offset */
>>>> +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1)
>>>> +
>>>> +
>>>> +/**
>>>> + * Initialize the packet
>>>> + *
>>>> + * Needs to be called if the user allocates a packet buffer, i.e. the
>>>> packet
>>>> + * has not been received from I/O through ODP.
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + */
>>>> +void odp_packet_init(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Convert from packet handle to buffer handle
>>>> + *
>>>> + * @param buf  Buffer handle
>>>> + *
>>>> + * @return Packet handle
>>>> + */
>>>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf);
>>>> +
>>>> +/**
>>>> + * Convert from buffer handle to packet handle
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return Buffer handle
>>>> + */
>>>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Set the packet length
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + * @param len  Length of packet in bytes
>>>> + */
>>>> +void odp_packet_set_len(odp_packet_t pkt, size_t len);
>>>> +
>>>> +/**
>>>> + * Get the packet length
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return   Packet length in bytes
>>>> + */
>>>> +size_t odp_packet_get_len(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Get address to the start of the packet buffer
>>>> + *
>>>> + * The address of the packet buffer is not necessarily the same as the
>>>> start
>>>> + * address of the received frame, e.g. an eth frame may be offset by 2
>>>> or 6
>>>> + * bytes to ensure 32 or 64-bit alignment of the IP header.
>>>> + * Use odp_packet_l2(pkt) to get the start address of a received valid
>>>> frame
>>>> + * or odp_packet_start(pkt) to get the start address even if no valid
>>>> L2 header
>>>> + * could be found.
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return  Pointer to the start of the packet buffer
>>>> + *
>>>> + * @see odp_packet_l2(), odp_packet_start()
>>>> + */
>>>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Get pointer to the start of the received frame
>>>> + *
>>>> + * The address of the packet buffer is not necessarily the same as the
>>>> start
>>>> + * address of the received frame, e.g. an eth frame may be offset by 2
>>>> or 6
>>>> + * bytes to ensure 32 or 64-bit alignment of the IP header.
>>>> + * Use odp_packet_l2(pkt) to get the start address of a received valid
>>>> eth frame
>>>> + *
>>>> + * odp_packet_start() will always return a pointer to the start of the
>>>> frame,
>>>> + * even if the frame is unrecognized and no valid L2 header could be
>>>> found.
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return  Pointer to the start of the received frame
>>>> + *
>>>> + * @see odp_packet_l2(), odp_packet_buf_addr()
>>>> + */
>>>> +uint8_t *odp_packet_start(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Get pointer to the start of the L2 frame
>>>> + *
>>>> + * The L2 frame header address is not necessarily the same as the
>>>> address of the
>>>> + * packet buffer, see odp_packet_buf_addr()
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return  Pointer to L2 header or NULL if not found
>>>> + *
>>>> + * @see odp_packet_buf_addr(), odp_packet_start()
>>>> + */
>>>> +uint8_t *odp_packet_l2(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Return the byte offset from the packet buffer to the L2 frame
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return  L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>>>> + */
>>>> +size_t odp_packet_l2_offset(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Set the byte offset to the L2 frame
>>>> + *
>>>> + * @param pkt     Packet handle
>>>> + * @param offset  L2 byte offset
>>>> + */
>>>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset);
>>>> +
>>>> +
>>>> +/**
>>>> + * Get pointer to the start of the L3 packet
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return  Pointer to L3 packet or NULL if not found
>>>> + *
>>>> + */
>>>> +uint8_t *odp_packet_l3(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Return the byte offset from the packet buffer to the L3 packet
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return  L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>>>> + */
>>>> +size_t odp_packet_l3_offset(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Set the byte offset to the L3 packet
>>>> + *
>>>> + * @param pkt     Packet handle
>>>> + * @param offset  L3 byte offset
>>>> + */
>>>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset);
>>>> +
>>>> +
>>>> +/**
>>>> + * Get pointer to the start of the L4 packet
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return  Pointer to L4 packet or NULL if not found
>>>> + *
>>>> + */
>>>> +uint8_t *odp_packet_l4(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Return the byte offset from the packet buffer to the L4 packet
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + *
>>>> + * @return  L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found
>>>> + */
>>>> +size_t odp_packet_l4_offset(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Set the byte offset to the L4 packet
>>>> + *
>>>> + * @param pkt     Packet handle
>>>> + * @param offset  L4 byte offset
>>>> + */
>>>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset);
>>>> +
>>>> +/**
>>>> + * Print (debug) information about the packet
>>>> + *
>>>> + * @param pkt  Packet handle
>>>> + */
>>>> +void odp_packet_print(odp_packet_t pkt);
>>>> +
>>>> +/**
>>>> + * Copy contents and metadata from pkt_src to pkt_dst
>>>> + * Useful when creating copies of packets
>>>> + *
>>>> + * @param pkt_dst Destination packet
>>>> + * @param pkt_src Source packet
>>>> + *
>>>> + * @return 0 if successful
>>>> + */
>>>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src);
>>>> +
>>>> +#ifdef __cplusplus
>>>> +}
>>>> +#endif
>>>> +
>>>> +#endif
>>>> diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h
>>>> b/platform/linux-dpdk/include/api/odp_pktio_types.h
>>>> new file mode 100644
>>>> index 0000000..b23e6da
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h
>>>> @@ -0,0 +1,45 @@
>>>> +
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#ifndef ODP_PKTIO_TYPES_H
>>>> +#define ODP_PKTIO_TYPES_H
>>>> +
>>>> +#ifdef __cplusplus
>>>> +extern "C" {
>>>> +#endif
>>>> +
>>>> +/* We should ensure that future enum values will never overlap,
>>>> otherwise
>>>> + * applications that want netmap suport might get in trouble if the
>>>> odp lib
>>>> + * was not built with netmap support and there are more types define
>>>> below
>>>> + */
>>>> +
>>>> +typedef enum {
>>>> +       ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1,
>>>> +       ODP_PKTIO_TYPE_SOCKET_MMSG,
>>>> +       ODP_PKTIO_TYPE_SOCKET_MMAP,
>>>> +       ODP_PKTIO_TYPE_NETMAP,
>>>> +       ODP_PKTIO_TYPE_DPDK,
>>>> +} odp_pktio_type_t;
>>>> +
>>>> +#include <odp_pktio_socket.h>
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +#include <odp_pktio_netmap.h>
>>>> +#endif
>>>> +
>>>> +typedef union odp_pktio_params_t {
>>>> +       odp_pktio_type_t type;
>>>> +       socket_params_t sock_params;
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +       netmap_params_t nm_params;
>>>> +#endif
>>>> +} odp_pktio_params_t;
>>>> +
>>>> +#ifdef __cplusplus
>>>> +}
>>>> +#endif
>>>> +
>>>> +#endif
>>>> diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h
>>>> b/platform/linux-dpdk/include/odp_buffer_internal.h
>>>> new file mode 100644
>>>> index 0000000..a47107c
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/odp_buffer_internal.h
>>>> @@ -0,0 +1,79 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +
>>>> +/**
>>>> + * @file
>>>> + *
>>>> + * ODP buffer descriptor - implementation internal
>>>> + */
>>>> +
>>>> +#ifndef ODP_BUFFER_INTERNAL_H_
>>>> +#define ODP_BUFFER_INTERNAL_H_
>>>> +
>>>> +#ifdef __cplusplus
>>>> +extern "C" {
>>>> +#endif
>>>> +
>>>> +#include <odp_std_types.h>
>>>> +#include <odp_atomic.h>
>>>> +#include <odp_buffer_pool.h>
>>>> +#include <odp_buffer.h>
>>>> +#include <odp_debug.h>
>>>> +#include <odp_align.h>
>>>> +#include <rte_mbuf.h>
>>>> +
>>>> +/* TODO: move these to correct files */
>>>> +
>>>> +typedef uint64_t odp_phys_addr_t;
>>>> +
>>>> +#define ODP_BUFFER_MAX_INDEX     (ODP_BUFFER_MAX_BUFFERS - 2)
>>>> +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1)
>>>> +
>>>> +#define ODP_BUFS_PER_CHUNK       16
>>>> +#define ODP_BUFS_PER_SCATTER      4
>>>> +
>>>> +#define ODP_BUFFER_TYPE_CHUNK    0xffff
>>>> +
>>>> +
>>>> +#define ODP_BUFFER_POOL_BITS   4
>>>> +#define ODP_BUFFER_INDEX_BITS  (32 - ODP_BUFFER_POOL_BITS)
>>>> +#define ODP_BUFFER_MAX_POOLS   (1 << ODP_BUFFER_POOL_BITS)
>>>> +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS)
>>>> +
>>>> +typedef union odp_buffer_bits_t {
>>>> +       uint32_t     u32;
>>>> +       odp_buffer_t handle;
>>>> +
>>>> +       struct {
>>>> +               uint32_t pool:ODP_BUFFER_POOL_BITS;
>>>> +               uint32_t index:ODP_BUFFER_INDEX_BITS;
>>>> +       };
>>>> +} odp_buffer_bits_t;
>>>> +
>>>> +
>>>> +/* forward declaration */
>>>> +struct odp_buffer_hdr_t;
>>>> +
>>>> +
>>>> +typedef struct rte_mbuf odp_buffer_hdr_t;
>>>> +
>>>> +
>>>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf);
>>>> +
>>>> +
>>>> +#ifdef __cplusplus
>>>> +}
>>>> +#endif
>>>> +
>>>> +#endif
>>>> +
>>>> +
>>>> +
>>>> +
>>>> +
>>>> +
>>>> +
>>>> diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>>> b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>>> new file mode 100644
>>>> index 0000000..1a36655
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
>>>> @@ -0,0 +1,90 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +
>>>> +/**
>>>> + * @file
>>>> + *
>>>> + * ODP buffer pool - internal header
>>>> + */
>>>> +
>>>> +#ifndef ODP_BUFFER_POOL_INTERNAL_H_
>>>> +#define ODP_BUFFER_POOL_INTERNAL_H_
>>>> +
>>>> +#ifdef __cplusplus
>>>> +extern "C" {
>>>> +#endif
>>>> +
>>>> +#include <odp_std_types.h>
>>>> +#include <odp_buffer_pool.h>
>>>> +#include <odp_buffer_internal.h>
>>>> +#include <odp_align.h>
>>>> +#include <odp_hints.h>
>>>> +#include <odp_config.h>
>>>> +#include <odp_debug.h>
>>>> +
>>>> +/* for DPDK */
>>>> +#include <rte_mempool.h>
>>>> +
>>>> +/* Use ticketlock instead of spinlock */
>>>> +#define POOL_USE_TICKETLOCK
>>>> +
>>>> +/* Extra error checks */
>>>> +/* #define POOL_ERROR_CHECK */
>>>> +
>>>> +
>>>> +#ifdef POOL_USE_TICKETLOCK
>>>> +#include <odp_ticketlock.h>
>>>> +#else
>>>> +#include <odp_spinlock.h>
>>>> +#endif
>>>> +
>>>> +
>>>> +struct pool_entry_s {
>>>> +#ifdef POOL_USE_TICKETLOCK
>>>> +       odp_ticketlock_t        lock ODP_ALIGNED_CACHE;
>>>> +#else
>>>> +       odp_spinlock_t          lock ODP_ALIGNED_CACHE;
>>>> +#endif
>>>> +
>>>> +       uint64_t                free_bufs;
>>>> +       char                    name[ODP_BUFFER_POOL_NAME_LEN];
>>>> +
>>>> +
>>>> +       odp_buffer_pool_t       pool ODP_ALIGNED_CACHE;
>>>> +       uintptr_t               buf_base;
>>>> +       size_t                  buf_size;
>>>> +       size_t                  buf_offset;
>>>> +       uint64_t                num_bufs;
>>>> +       void                   *pool_base_addr;
>>>> +       uint64_t                pool_size;
>>>> +       size_t                  payload_size;
>>>> +       size_t                  payload_align;
>>>> +       int                     buf_type;
>>>> +       size_t                  hdr_size;
>>>> +};
>>>> +
>>>> +
>>>> +extern void *pool_entry_ptr[];
>>>> +
>>>> +
>>>> +static inline void *get_pool_entry(odp_buffer_pool_t pool_id)
>>>> +{
>>>> +       return pool_entry_ptr[pool_id];
>>>> +}
>>>> +
>>>> +
>>>> +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf)
>>>> +{
>>>> +       return (odp_buffer_hdr_t *)buf;
>>>> +}
>>>> +
>>>> +
>>>> +#ifdef __cplusplus
>>>> +}
>>>> +#endif
>>>> +
>>>> +#endif
>>>> diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h
>>>> b/platform/linux-dpdk/include/odp_packet_dpdk.h
>>>> new file mode 100644
>>>> index 0000000..0b3db08
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
>>>> @@ -0,0 +1,88 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#ifndef ODP_PACKET_DPDK_H
>>>> +#define ODP_PACKET_DPDK_H
>>>> +
>>>> +#include <stdint.h>
>>>> +#include <net/if.h>
>>>> +
>>>> +#include <helper/odp_eth.h>
>>>> +#include <helper/odp_packet_helper.h>
>>>> +#include <odp_align.h>
>>>> +#include <odp_debug.h>
>>>> +#include <odp_packet.h>
>>>> +#include <odp_packet_internal.h>
>>>> +#include <odp_buffer_pool.h>
>>>> +#include <odp_buffer_pool_internal.h>
>>>> +#include <odp_buffer_internal.h>
>>>> +#include <odp_std_types.h>
>>>> +
>>>> +#include <rte_config.h>
>>>> +#include <rte_memory.h>
>>>> +#include <rte_memzone.h>
>>>> +#include <rte_launch.h>
>>>> +#include <rte_tailq.h>
>>>> +#include <rte_eal.h>
>>>> +#include <rte_per_lcore.h>
>>>> +#include <rte_lcore.h>
>>>> +#include <rte_branch_prediction.h>
>>>> +#include <rte_prefetch.h>
>>>> +#include <rte_cycles.h>
>>>> +#include <rte_errno.h>
>>>> +#include <rte_debug.h>
>>>> +#include <rte_log.h>
>>>> +#include <rte_byteorder.h>
>>>> +#include <rte_pci.h>
>>>> +#include <rte_random.h>
>>>> +#include <rte_ether.h>
>>>> +#include <rte_ethdev.h>
>>>> +#include <rte_hash.h>
>>>> +#include <rte_jhash.h>
>>>> +#include <rte_hash_crc.h>
>>>> +
>>>> +
>>>> +#define ODP_DPDK_MODE_HW       0
>>>> +#define ODP_DPDK_MODE_SW       1
>>>> +
>>>> +#define DPDK_BLOCKING_IO
>>>> +
>>>> +/** Packet socket using dpdk mmaped rings for both Rx and Tx */
>>>> +typedef struct {
>>>> +       odp_buffer_pool_t pool;
>>>> +
>>>> +       /********************************/
>>>> +       char ifname[32];
>>>> +       uint8_t portid;
>>>> +       uint16_t queueid;
>>>> +} pkt_dpdk_t;
>>>> +
>>>> +/**
>>>> + * Configure an interface to work in dpdk mode
>>>> + */
>>>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
>>>> +                  odp_buffer_pool_t pool);
>>>> +
>>>> +/**
>>>> + * Switch interface from dpdk mode to normal mode
>>>> + */
>>>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk);
>>>> +
>>>> +/**
>>>> + * Receive packets using dpdk
>>>> + */
>>>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t
>>>> pkt_table[],
>>>> +                 unsigned len);
>>>> +
>>>> +/**
>>>> + * Send packets using dpdk
>>>> + */
>>>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t
>>>> pkt_table[],
>>>> +                 unsigned len);
>>>> +
>>>> +int odp_init_dpdk(void);
>>>> +#endif
>>>> +
>>>> diff --git a/platform/linux-dpdk/include/odp_packet_internal.h
>>>> b/platform/linux-dpdk/include/odp_packet_internal.h
>>>> new file mode 100644
>>>> index 0000000..d9057a2
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/odp_packet_internal.h
>>>> @@ -0,0 +1,140 @@
>>>> +/* Copyright (c) 2014, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +
>>>> +/**
>>>> + * @file
>>>> + *
>>>> + * ODP packet descriptor - implementation internal
>>>> + */
>>>> +
>>>> +#ifndef ODP_PACKET_INTERNAL_H_
>>>> +#define ODP_PACKET_INTERNAL_H_
>>>> +
>>>> +#ifdef __cplusplus
>>>> +extern "C" {
>>>> +#endif
>>>> +
>>>> +#include <odp_align.h>
>>>> +#include <odp_debug.h>
>>>> +#include <odp_buffer_internal.h>
>>>> +#include <odp_buffer_pool_internal.h>
>>>> +#include <odp_packet.h>
>>>> +#include <odp_packet_io.h>
>>>> +
>>>> +/**
>>>> + * Packet input & protocol flags
>>>> + */
>>>> +typedef union {
>>>> +       /* All input flags */
>>>> +       uint32_t all;
>>>> +
>>>> +       struct {
>>>> +               /* 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:1;     /**< 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;
>>>> +
>>>> +       struct {
>>>> +               /* 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;
>>>> +
>>>> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t),
>>>> ERROR_FLAGS_SIZE_ERROR);
>>>> +
>>>> +/**
>>>> + * Packet output flags
>>>> + */
>>>> +typedef union {
>>>> +       /* All output flags */
>>>> +       uint32_t all;
>>>> +
>>>> +       struct {
>>>> +               /* 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 {
>>>> +       /* common buffer header */
>>>> +       odp_buffer_hdr_t buf_hdr;
>>>> +
>>>> +       input_flags_t  input_flags;
>>>> +       error_flags_t  error_flags;
>>>> +       output_flags_t output_flags;
>>>> +
>>>> +       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;
>>>> +
>>>> +/**
>>>> + * Return the packet header
>>>> + */
>>>> +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt)
>>>> +{
>>>> +       return (odp_packet_hdr_t *)pkt;
>>>> +}
>>>> +
>>>> +/**
>>>> + * Parse packet and set internal metadata
>>>> + */
>>>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset);
>>>> +
>>>> +#ifdef __cplusplus
>>>> +}
>>>> +#endif
>>>> +
>>>> +#endif
>>>> +
>>>> diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h
>>>> b/platform/linux-dpdk/include/odp_packet_io_internal.h
>>>> new file mode 100644
>>>> index 0000000..5948063
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
>>>> @@ -0,0 +1,52 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +
>>>> +/**
>>>> + * @file
>>>> + *
>>>> + * ODP packet IO - implementation internal
>>>> + */
>>>> +
>>>> +#ifndef ODP_PACKET_IO_INTERNAL_H_
>>>> +#define ODP_PACKET_IO_INTERNAL_H_
>>>> +
>>>> +#ifdef __cplusplus
>>>> +extern "C" {
>>>> +#endif
>>>> +
>>>> +#include <odp_spinlock.h>
>>>> +#include <odp_packet_socket.h>
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +#include <odp_packet_netmap.h>
>>>> +#endif
>>>> +#include <odp_packet_dpdk.h>
>>>> +
>>>> +struct pktio_entry {
>>>> +       odp_spinlock_t lock;            /**< entry spinlock */
>>>> +       int taken;                      /**< is entry taken(1) or
>>>> free(0) */
>>>> +       odp_queue_t inq_default;        /**< default input queue, if
>>>> set */
>>>> +       odp_queue_t outq_default;       /**< default out queue */
>>>> +       odp_pktio_params_t params;      /**< pktio parameters */
>>>> +       pkt_sock_t pkt_sock;            /**< using socket API for IO */
>>>> +       pkt_sock_mmap_t pkt_sock_mmap;  /**< using socket mmap API for
>>>> IO */
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +       pkt_netmap_t pkt_nm;            /**< using netmap API for IO */
>>>> +#endif
>>>> +       pkt_dpdk_t pkt_dpdk;            /**< using DPDK API for IO */
>>>> +};
>>>> +
>>>> +typedef union {
>>>> +       struct pktio_entry s;
>>>> +       uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct
>>>> pktio_entry))];
>>>> +} pktio_entry_t;
>>>> +
>>>> +#ifdef __cplusplus
>>>> +}
>>>> +#endif
>>>> +
>>>> +#endif
>>>> +
>>>> diff --git a/platform/linux-dpdk/source/odp_buffer.c
>>>> b/platform/linux-dpdk/source/odp_buffer.c
>>>> new file mode 100644
>>>> index 0000000..bfb5ff6
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/source/odp_buffer.c
>>>> @@ -0,0 +1,102 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#include <odp_buffer.h>
>>>> +#include <odp_buffer_internal.h>
>>>> +#include <odp_buffer_pool_internal.h>
>>>> +
>>>> +#include <string.h>
>>>> +#include <stdio.h>
>>>> +
>>>> +
>>>> +void *odp_buffer_addr(odp_buffer_t buf)
>>>> +{
>>>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>>>> +
>>>> +       return hdr->buf_addr;
>>>> +}
>>>> +
>>>> +
>>>> +size_t odp_buffer_size(odp_buffer_t buf)
>>>> +{
>>>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>>>> +
>>>> +       return hdr->buf_len;
>>>> +}
>>>> +
>>>> +
>>>> +int odp_buffer_type(odp_buffer_t buf)
>>>> +{
>>>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>>>> +
>>>> +       return hdr->type;
>>>> +}
>>>> +
>>>> +
>>>> +int odp_buffer_is_scatter(odp_buffer_t buf)
>>>> +{
>>>> +       odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
>>>> +
>>>> +       if (hdr->refcnt == 0)
>>>> +               return 0;
>>>> +       else
>>>> +               return 1;
>>>> +}
>>>> +
>>>> +
>>>> +int odp_buffer_is_valid(odp_buffer_t buf)
>>>> +{
>>>> +       odp_buffer_bits_t handle;
>>>> +
>>>> +       handle.u32 = buf;
>>>> +
>>>> +       return (handle.index != ODP_BUFFER_INVALID_INDEX);
>>>> +}
>>>> +
>>>> +
>>>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf)
>>>> +{
>>>> +       odp_buffer_hdr_t *hdr;
>>>> +       int len = 0;
>>>> +
>>>> +       if (!odp_buffer_is_valid(buf)) {
>>>> +               printf("Buffer is not valid.\n");
>>>> +               return len;
>>>> +       }
>>>> +
>>>> +       hdr = odp_buf_to_hdr(buf);
>>>> +
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "Buffer\n");
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  pool         %"PRIu64"\n", (int64_t)
>>>> hdr->pool);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  phy_addr     %"PRIu64"\n",
>>>> hdr->buf_physaddr);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  addr         %p\n",        hdr->buf_addr);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  size         %u\n",        hdr->buf_len);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  ref_count    %i\n",        hdr->refcnt);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  type         %i\n",        hdr->type);
>>>> +
>>>> +       return len;
>>>> +}
>>>> +
>>>> +
>>>> +void odp_buffer_print(odp_buffer_t buf)
>>>> +{
>>>> +       int max_len = 512;
>>>> +       char str[max_len];
>>>> +       int len;
>>>> +
>>>> +       len = odp_buffer_snprint(str, max_len-1, buf);
>>>> +       str[len] = 0;
>>>> +
>>>> +       printf("\n%s\n", str);
>>>> +}
>>>> +
>>>> diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c
>>>> b/platform/linux-dpdk/source/odp_buffer_pool.c
>>>> new file mode 100644
>>>> index 0000000..de90275
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/source/odp_buffer_pool.c
>>>> @@ -0,0 +1,156 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#include <odp_std_types.h>
>>>> +#include <odp_buffer_pool.h>
>>>> +#include <odp_buffer_pool_internal.h>
>>>> +#include <odp_buffer_internal.h>
>>>> +#include <odp_packet_internal.h>
>>>> +#include <odp_shared_memory.h>
>>>> +#include <odp_align.h>
>>>> +#include <odp_internal.h>
>>>> +#include <odp_config.h>
>>>> +#include <odp_hints.h>
>>>> +#include <odp_debug.h>
>>>> +
>>>> +#include <string.h>
>>>> +#include <stdlib.h>
>>>> +
>>>> +/* for DPDK */
>>>> +#include <odp_packet_dpdk.h>
>>>> +
>>>> +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) +
>>>> RTE_PKTMBUF_HEADROOM)
>>>> +#define NB_MBUF   8192
>>>> +
>>>> +#ifdef POOL_USE_TICKETLOCK
>>>> +#include <odp_ticketlock.h>
>>>> +#define LOCK(a)      odp_ticketlock_lock(a)
>>>> +#define UNLOCK(a)    odp_ticketlock_unlock(a)
>>>> +#define LOCK_INIT(a) odp_ticketlock_init(a)
>>>> +#else
>>>> +#include <odp_spinlock.h>
>>>> +#define LOCK(a)      odp_spinlock_lock(a)
>>>> +#define UNLOCK(a)    odp_spinlock_unlock(a)
>>>> +#define LOCK_INIT(a) odp_spinlock_init(a)
>>>> +#endif
>>>> +
>>>> +
>>>> +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
>>>> +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
>>>> +#endif
>>>> +
>>>> +#define NULL_INDEX ((uint32_t)-1)
>>>> +
>>>> +
>>>> +typedef union pool_entry_u {
>>>> +       struct pool_entry_s s;
>>>> +
>>>> +       uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct
>>>> pool_entry_s))];
>>>> +
>>>> +} pool_entry_t;
>>>> +
>>>> +
>>>> +typedef struct pool_table_t {
>>>> +       pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS];
>>>> +
>>>> +} pool_table_t;
>>>> +
>>>> +
>>>> +/* The pool table */
>>>> +static pool_table_t *pool_tbl;
>>>> +
>>>> +/* Pool entry pointers (for inlining) */
>>>> +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS];
>>>> +
>>>> +
>>>> +int odp_buffer_pool_init_global(void)
>>>> +{
>>>> +       odp_buffer_pool_t i;
>>>> +
>>>> +       pool_tbl = odp_shm_reserve("odp_buffer_pools",
>>>> +                                  sizeof(pool_table_t),
>>>> +                                  sizeof(pool_entry_t));
>>>> +
>>>> +       if (pool_tbl == NULL)
>>>> +               return -1;
>>>> +
>>>> +       memset(pool_tbl, 0, sizeof(pool_table_t));
>>>> +
>>>> +
>>>> +       for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) {
>>>> +               /* init locks */
>>>> +               pool_entry_t *pool = &pool_tbl->pool[i];
>>>> +               LOCK_INIT(&pool->s.lock);
>>>> +               pool->s.pool = i;
>>>> +
>>>> +               pool_entry_ptr[i] = pool;
>>>> +       }
>>>> +
>>>> +       ODP_DBG("\nBuffer pool init global\n");
>>>> +       ODP_DBG("  pool_entry_s size     %zu\n", sizeof(struct
>>>> pool_entry_s));
>>>> +       ODP_DBG("  pool_entry_t size     %zu\n", sizeof(pool_entry_t));
>>>> +       ODP_DBG("  odp_buffer_hdr_t size %zu\n",
>>>> sizeof(odp_buffer_hdr_t));
>>>> +       ODP_DBG("\n");
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +
>>>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name,
>>>> +                                        void *base_addr, uint64_t size,
>>>> +                                        size_t buf_size, size_t
>>>> buf_align,
>>>> +                                        int buf_type)
>>>> +{
>>>> +       struct rte_mempool *pktmbuf_pool = NULL;
>>>> +       ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n",
>>>> name,
>>>> +               (uint64_t) base_addr, (unsigned) size,
>>>> +               (unsigned) buf_size, (unsigned) buf_align,
>>>> +               buf_type);
>>>> +
>>>> +       pktmbuf_pool =
>>>> +               rte_mempool_create(name, NB_MBUF,
>>>> +                                  MBUF_SIZE, 32,
>>>> +                                  sizeof(struct
>>>> rte_pktmbuf_pool_private),
>>>> +                                  rte_pktmbuf_pool_init, NULL,
>>>> +                                  rte_pktmbuf_init, NULL,
>>>> +                                  rte_socket_id(), 0);
>>>> +       if (pktmbuf_pool == NULL) {
>>>> +               ODP_ERR("Cannot init DPDK mbuf pool\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       return (odp_buffer_pool_t) pktmbuf_pool;
>>>> +}
>>>> +
>>>> +
>>>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name)
>>>> +{
>>>> +       struct rte_mempool *mp = NULL;
>>>> +
>>>> +       mp = rte_mempool_lookup(name);
>>>> +       if (mp == NULL)
>>>> +               return ODP_BUFFER_POOL_INVALID;
>>>> +
>>>> +       return (odp_buffer_pool_t)mp;
>>>> +}
>>>> +
>>>> +
>>>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id)
>>>> +{
>>>> +       return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool
>>>> *)pool_id);
>>>> +}
>>>> +
>>>> +
>>>> +void odp_buffer_free(odp_buffer_t buf)
>>>> +{
>>>> +       rte_pktmbuf_free((struct rte_mbuf *)buf);
>>>> +}
>>>> +
>>>> +
>>>> +void odp_buffer_pool_print(odp_buffer_pool_t pool_id)
>>>> +{
>>>> +       rte_mempool_dump((const struct rte_mempool *)pool_id);
>>>> +}
>>>> diff --git a/platform/linux-dpdk/source/odp_init.c
>>>> b/platform/linux-dpdk/source/odp_init.c
>>>> new file mode 100644
>>>> index 0000000..ecc2066
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/source/odp_init.c
>>>> @@ -0,0 +1,113 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#include <odp_init.h>
>>>> +#include <odp_internal.h>
>>>> +#include <odp_debug.h>
>>>> +#include <odp_packet_dpdk.h>
>>>> +
>>>> +int odp_init_dpdk(void)
>>>> +{
>>>> +       int test_argc = 5;
>>>> +       char *test_argv[6];
>>>> +       int core_count, i, num_cores = 0;
>>>> +       char core_mask[8];
>>>> +
>>>> +       core_count  = odp_sys_core_count();
>>>> +       for (i = 0; i < core_count; i++)
>>>> +               num_cores += (0x1 << i);
>>>> +       sprintf(core_mask, "%x", num_cores);
>>>> +
>>>> +       test_argv[0] = malloc(sizeof("odp_dpdk"));
>>>> +       strcpy(test_argv[0], "odp_dpdk");
>>>> +       test_argv[1] = malloc(sizeof("-c"));
>>>> +       strcpy(test_argv[1], "-c");
>>>> +       test_argv[2] = malloc(sizeof(core_mask));
>>>> +       strcpy(test_argv[2], core_mask);
>>>> +       test_argv[3] = malloc(sizeof("-n"));
>>>> +       strcpy(test_argv[3], "-n");
>>>> +       test_argv[4] = malloc(sizeof("3"));
>>>> +       strcpy(test_argv[4], "3");
>>>> +
>>>> +       if (rte_eal_init(test_argc, (char **)test_argv) < 0) {
>>>> +               ODP_ERR("Cannot init the Intel DPDK EAL!");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (rte_pmd_init_all() < 0) {
>>>> +               ODP_ERR("Cannot init pmd\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (rte_eal_pci_probe() < 0) {
>>>> +               ODP_ERR("Cannot probe PCI\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int odp_init_global(void)
>>>> +{
>>>> +       odp_thread_init_global();
>>>> +
>>>> +       odp_system_info_init();
>>>> +
>>>> +       if (odp_init_dpdk()) {
>>>> +               ODP_ERR("ODP dpdk init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (odp_shm_init_global()) {
>>>> +               ODP_ERR("ODP shm init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (odp_buffer_pool_init_global()) {
>>>> +               ODP_ERR("ODP buffer pool init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (odp_queue_init_global()) {
>>>> +               ODP_ERR("ODP queue init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (odp_schedule_init_global()) {
>>>> +               ODP_ERR("ODP schedule init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (odp_pktio_init_global()) {
>>>> +               ODP_ERR("ODP packet io init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (odp_timer_init_global()) {
>>>> +               ODP_ERR("ODP timer init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +
>>>> +int odp_init_local(int thr_id)
>>>> +{
>>>> +       odp_thread_init_local(thr_id);
>>>> +
>>>> +       if (odp_pktio_init_local()) {
>>>> +               ODP_ERR("ODP packet io local init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       if (odp_schedule_init_local()) {
>>>> +               ODP_ERR("ODP schedule local init failed.\n");
>>>> +               return -1;
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> diff --git a/platform/linux-dpdk/source/odp_packet.c
>>>> b/platform/linux-dpdk/source/odp_packet.c
>>>> new file mode 100644
>>>> index 0000000..c34e626
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/source/odp_packet.c
>>>> @@ -0,0 +1,374 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#include <odp_packet.h>
>>>> +#include <odp_packet_internal.h>
>>>> +#include <odp_hints.h>
>>>> +#include <odp_byteorder.h>
>>>> +
>>>> +#include <helper/odp_eth.h>
>>>> +#include <helper/odp_ip.h>
>>>> +
>>>> +#include <string.h>
>>>> +#include <stdio.h>
>>>> +
>>>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
>>>> odp_ipv4hdr_t *ipv4,
>>>> +                               size_t *offset_out);
>>>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
>>>> odp_ipv6hdr_t *ipv6,
>>>> +                               size_t *offset_out);
>>>> +
>>>> +void odp_packet_init(odp_packet_t pkt)
>>>> +{
>>>> +       odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
>>>> +       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>>>> buf_hdr);
>>>> +       uint8_t *start;
>>>> +       size_t len;
>>>> +
>>>> +       start = (uint8_t *)pkt_hdr + start_offset;
>>>> +       len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
>>>> +       memset(start, 0, len);
>>>> +
>>>> +       pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>>>> +       pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>>>> +       pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
>>>> +}
>>>> +
>>>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf)
>>>> +{
>>>> +       return (odp_packet_t)buf;
>>>> +}
>>>> +
>>>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt)
>>>> +{
>>>> +       return (odp_buffer_t)pkt;
>>>> +}
>>>> +
>>>> +void odp_packet_set_len(odp_packet_t pkt, size_t len)
>>>> +{
>>>> +       /* for rte_pktmbuf */
>>>> +       odp_buffer_hdr_t *buf_hdr =
>>>> odp_buf_to_hdr(odp_buffer_from_packet(pkt));
>>>> +       buf_hdr->pkt.data_len = len;
>>>> +
>>>> +       odp_packet_hdr(pkt)->frame_len = len;
>>>> +}
>>>> +
>>>> +size_t odp_packet_get_len(odp_packet_t pkt)
>>>> +{
>>>> +       return odp_packet_hdr(pkt)->frame_len;
>>>> +}
>>>> +
>>>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt)
>>>> +{
>>>> +       return odp_buffer_addr(odp_buffer_from_packet(pkt));
>>>> +}
>>>> +
>>>> +uint8_t *odp_packet_start(odp_packet_t pkt)
>>>> +{
>>>> +       return odp_packet_buf_addr(pkt) +
>>>> odp_packet_hdr(pkt)->frame_offset;
>>>> +}
>>>> +
>>>> +
>>>> +uint8_t *odp_packet_l2(odp_packet_t pkt)
>>>> +{
>>>> +       const size_t offset = odp_packet_l2_offset(pkt);
>>>> +
>>>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>>>> +               return NULL;
>>>> +
>>>> +       return odp_packet_buf_addr(pkt) + offset;
>>>> +}
>>>> +
>>>> +size_t odp_packet_l2_offset(odp_packet_t pkt)
>>>> +{
>>>> +       return odp_packet_hdr(pkt)->l2_offset;
>>>> +}
>>>> +
>>>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset)
>>>> +{
>>>> +       odp_packet_hdr(pkt)->l2_offset = offset;
>>>> +}
>>>> +
>>>> +uint8_t *odp_packet_l3(odp_packet_t pkt)
>>>> +{
>>>> +       const size_t offset = odp_packet_l3_offset(pkt);
>>>> +
>>>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>>>> +               return NULL;
>>>> +
>>>> +       return odp_packet_buf_addr(pkt) + offset;
>>>> +}
>>>> +
>>>> +size_t odp_packet_l3_offset(odp_packet_t pkt)
>>>> +{
>>>> +       return odp_packet_hdr(pkt)->l3_offset;
>>>> +}
>>>> +
>>>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset)
>>>> +{
>>>> +       odp_packet_hdr(pkt)->l3_offset = offset;
>>>> +}
>>>> +
>>>> +uint8_t *odp_packet_l4(odp_packet_t pkt)
>>>> +{
>>>> +       const size_t offset = odp_packet_l4_offset(pkt);
>>>> +
>>>> +       if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
>>>> +               return NULL;
>>>> +
>>>> +       return odp_packet_buf_addr(pkt) + offset;
>>>> +}
>>>> +
>>>> +size_t odp_packet_l4_offset(odp_packet_t pkt)
>>>> +{
>>>> +       return odp_packet_hdr(pkt)->l4_offset;
>>>> +}
>>>> +
>>>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset)
>>>> +{
>>>> +       odp_packet_hdr(pkt)->l4_offset = offset;
>>>> +}
>>>> +
>>>> +/**
>>>> + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP
>>>> + *
>>>> + * Internal function: caller is resposible for passing only valid
>>>> packet handles
>>>> + * , lengths and offsets (usually done&called in packet input).
>>>> + *
>>>> + * @param pkt        Packet handle
>>>> + * @param len        Packet length in bytes
>>>> + * @param frame_offset  Byte offset to L2 header
>>>> + */
>>>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t
>>>> frame_offset)
>>>> +{
>>>> +       odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
>>>> +       odp_ethhdr_t *eth;
>>>> +       odp_vlanhdr_t *vlan;
>>>> +       odp_ipv4hdr_t *ipv4;
>>>> +       odp_ipv6hdr_t *ipv6;
>>>> +       uint16_t ethtype;
>>>> +       size_t offset = 0;
>>>> +       uint8_t ip_proto = 0;
>>>> +
>>>> +       pkt_hdr->input_flags.eth = 1;
>>>> +       pkt_hdr->frame_offset = frame_offset;
>>>> +       pkt_hdr->frame_len = len;
>>>> +
>>>> +       if (odp_unlikely(len < ODP_ETH_LEN_MIN)) {
>>>> +               pkt_hdr->error_flags.frame_len = 1;
>>>> +               return;
>>>> +       } else if (len > ODP_ETH_LEN_MAX) {
>>>> +               pkt_hdr->input_flags.jumbo = 1;
>>>> +       }
>>>> +
>>>> +       /* Assume valid L2 header, no CRC/FCS check in SW */
>>>> +       pkt_hdr->input_flags.l2 = 1;
>>>> +       pkt_hdr->l2_offset = frame_offset;
>>>> +
>>>> +       eth = (odp_ethhdr_t *)odp_packet_start(pkt);
>>>> +       ethtype = odp_be_to_cpu_16(eth->type);
>>>> +       vlan = (odp_vlanhdr_t *)&eth->type;
>>>> +
>>>> +       if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
>>>> +               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->input_flags.vlan = 1;
>>>> +               ethtype = odp_be_to_cpu_16(vlan->tpid);
>>>> +               offset += sizeof(odp_vlanhdr_t);
>>>> +       }
>>>> +
>>>> +       /* Set l3_offset+flag only for known ethtypes */
>>>> +       switch (ethtype) {
>>>> +       case ODP_ETHTYPE_IPV4:
>>>> +               pkt_hdr->input_flags.ipv4 = 1;
>>>> +               pkt_hdr->input_flags.l3 = 1;
>>>> +               pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN +
>>>> offset;
>>>> +               ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
>>>> +               ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset);
>>>> +               break;
>>>> +       case ODP_ETHTYPE_IPV6:
>>>> +               pkt_hdr->input_flags.ipv6 = 1;
>>>> +               pkt_hdr->input_flags.l3 = 1;
>>>> +               pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN +
>>>> offset;
>>>> +               ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt);
>>>> +               ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset);
>>>> +               break;
>>>> +       case ODP_ETHTYPE_ARP:
>>>> +               pkt_hdr->input_flags.arp = 1;
>>>> +               /* fall through */
>>>> +       default:
>>>> +               ip_proto = 0;
>>>> +               break;
>>>> +       }
>>>> +
>>>> +       switch (ip_proto) {
>>>> +       case ODP_IPPROTO_UDP:
>>>> +               pkt_hdr->input_flags.udp = 1;
>>>> +               pkt_hdr->input_flags.l4 = 1;
>>>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>>>> +               break;
>>>> +       case ODP_IPPROTO_TCP:
>>>> +               pkt_hdr->input_flags.tcp = 1;
>>>> +               pkt_hdr->input_flags.l4 = 1;
>>>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>>>> +               break;
>>>> +       case ODP_IPPROTO_SCTP:
>>>> +               pkt_hdr->input_flags.sctp = 1;
>>>> +               pkt_hdr->input_flags.l4 = 1;
>>>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>>>> +               break;
>>>> +       case ODP_IPPROTO_ICMP:
>>>> +               pkt_hdr->input_flags.icmp = 1;
>>>> +               pkt_hdr->input_flags.l4 = 1;
>>>> +               pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
>>>> +               break;
>>>> +       default:
>>>> +               /* 0 or unhandled IP protocols, don't set L4
>>>> flag+offset */
>>>> +               if (pkt_hdr->input_flags.ipv6) {
>>>> +                       /* IPv6 next_hdr is not L4, mark as IP-option
>>>> instead */
>>>> +                       pkt_hdr->input_flags.ipopt = 1;
>>>> +               }
>>>> +               break;
>>>> +       }
>>>> +}
>>>> +
>>>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
>>>> odp_ipv4hdr_t *ipv4,
>>>> +                               size_t *offset_out)
>>>> +{
>>>> +       uint8_t ihl;
>>>> +       uint16_t frag_offset;
>>>> +
>>>> +       ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl);
>>>> +       if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) {
>>>> +               pkt_hdr->error_flags.ip_err = 1;
>>>> +               return 0;
>>>> +       }
>>>> +
>>>> +       if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) {
>>>> +               pkt_hdr->input_flags.ipopt = 1;
>>>> +               return 0;
>>>> +       }
>>>> +
>>>> +       /* A packet is a fragment if:
>>>> +       *  "more fragments" flag is set (all fragments except the last)
>>>> +       *     OR
>>>> +       *  "fragment offset" field is nonzero (all fragments except the
>>>> first)
>>>> +       */
>>>> +       frag_offset = odp_be_to_cpu_16(ipv4->frag_offset);
>>>> +       if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) {
>>>> +               pkt_hdr->input_flags.ipfrag = 1;
>>>> +               return 0;
>>>> +       }
>>>> +
>>>> +       if (ipv4->proto == ODP_IPPROTO_ESP ||
>>>> +           ipv4->proto == ODP_IPPROTO_AH) {
>>>> +               pkt_hdr->input_flags.ipsec = 1;
>>>> +               return 0;
>>>> +       }
>>>> +
>>>> +       /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after
>>>> return */
>>>> +
>>>> +       *offset_out = sizeof(uint32_t) * ihl;
>>>> +       return ipv4->proto;
>>>> +}
>>>> +
>>>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
>>>> odp_ipv6hdr_t *ipv6,
>>>> +                               size_t *offset_out)
>>>> +{
>>>> +       if (ipv6->next_hdr == ODP_IPPROTO_ESP ||
>>>> +           ipv6->next_hdr == ODP_IPPROTO_AH) {
>>>> +               pkt_hdr->input_flags.ipopt = 1;
>>>> +               pkt_hdr->input_flags.ipsec = 1;
>>>> +               return 0;
>>>> +       }
>>>> +
>>>> +       if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) {
>>>> +               pkt_hdr->input_flags.ipopt = 1;
>>>> +               pkt_hdr->input_flags.ipfrag = 1;
>>>> +               return 0;
>>>> +       }
>>>> +
>>>> +       /* Don't step through more extensions */
>>>> +       *offset_out = ODP_IPV6HDR_LEN;
>>>> +       return ipv6->next_hdr;
>>>> +}
>>>> +
>>>> +void odp_packet_print(odp_packet_t pkt)
>>>> +{
>>>> +       int max_len = 512;
>>>> +       char str[max_len];
>>>> +       int len = 0;
>>>> +       int n = max_len-1;
>>>> +       odp_packet_hdr_t *hdr = odp_packet_hdr(pkt);
>>>> +
>>>> +       len += snprintf(&str[len], n-len, "Packet ");
>>>> +       len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  input_flags  0x%x\n", hdr->input_flags.all);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  error_flags  0x%x\n", hdr->error_flags.all);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  output_flags 0x%x\n", hdr->output_flags.all);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  frame_offset %u\n", hdr->frame_offset);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  l2_offset    %u\n", hdr->l2_offset);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  l3_offset    %u\n", hdr->l3_offset);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  l4_offset    %u\n", hdr->l4_offset);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  frame_len    %u\n", hdr->frame_len);
>>>> +       len += snprintf(&str[len], n-len,
>>>> +                       "  input        %u\n", hdr->input);
>>>> +       str[len] = '\0';
>>>> +
>>>> +       printf("\n%s\n", str);
>>>> +}
>>>> +
>>>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src)
>>>> +{
>>>> +       odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst);
>>>> +       odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src);
>>>> +       const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t,
>>>> buf_hdr);
>>>> +       uint8_t *start_src;
>>>> +       uint8_t *start_dst;
>>>> +       size_t len;
>>>> +
>>>> +       if (pkt_dst == ODP_PACKET_INVALID || pkt_src ==
>>>> ODP_PACKET_INVALID)
>>>> +               return -1;
>>>> +
>>>> +       /* if (pkt_hdr_dst->buf_hdr.size < */
>>>> +       /*      pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */
>>>> +       if (pkt_hdr_dst->buf_hdr.buf_len <
>>>> +               pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset)
>>>> +               return -1;
>>>> +
>>>> +       /* Copy packet header */
>>>> +       start_dst = (uint8_t *)pkt_hdr_dst + start_offset;
>>>> +       start_src = (uint8_t *)pkt_hdr_src + start_offset;
>>>> +       len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
>>>> +       memcpy(start_dst, start_src, len);
>>>> +
>>>> +       /* Copy frame payload */
>>>> +       start_dst = (uint8_t *)odp_packet_start(pkt_dst);
>>>> +       start_src = (uint8_t *)odp_packet_start(pkt_src);
>>>> +       len = pkt_hdr_src->frame_len;
>>>> +       memcpy(start_dst, start_src, len);
>>>> +
>>>> +       /* Copy useful things from the buffer header */
>>>> +       /* pkt_hdr_dst->buf_hdr.cur_offset =
>>>> pkt_hdr_src->buf_hdr.cur_offset; */
>>>> +
>>>> +       /* Create a copy of the scatter list */
>>>> +       /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */
>>>> +       /*                      odp_buffer_from_packet(pkt_src)); */
>>>> +
>>>> +       return 0;
>>>> +}
>>>> diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c
>>>> b/platform/linux-dpdk/source/odp_packet_dpdk.c
>>>> new file mode 100644
>>>> index 0000000..6d16bbe
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c
>>>> @@ -0,0 +1,177 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#define _GNU_SOURCE
>>>> +#include <stdio.h>
>>>> +#include <errno.h>
>>>> +#include <sys/types.h>
>>>> +#include <sys/stat.h>
>>>> +#include <sys/ioctl.h>
>>>> +#include <sys/mman.h>
>>>> +#include <poll.h>
>>>> +#include <unistd.h>
>>>> +#include <fcntl.h>
>>>> +#include <string.h>
>>>> +#include <stdlib.h>
>>>> +
>>>> +#include <linux/ethtool.h>
>>>> +#include <linux/sockios.h>
>>>> +
>>>> +#include <odp_hints.h>
>>>> +#include <odp_thread.h>
>>>> +
>>>> +#include <odp_packet_dpdk.h>
>>>> +#include <net/if.h>
>>>> +
>>>> +/*
>>>> + * RX and TX Prefetch, Host, and Write-back threshold values should be
>>>> + * carefully set for optimal performance. Consult the network
>>>> + * controller's datasheet and supporting DPDK documentation for
>>>> guidance
>>>> + * on how these parameters should be set.
>>>> + */
>>>> +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg.
>>>> */
>>>> +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
>>>> +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold
>>>> reg. */
>>>> +
>>>> +/*
>>>> + * These default values are optimized for use with the Intel(R) 82599
>>>> 10 GbE
>>>> + * Controller and the DPDK ixgbe PMD. Consider using other values for
>>>> other
>>>> + * network controllers and/or network drivers.
>>>> + */
>>>> +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold
>>>> reg. */
>>>> +#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
>>>> +#define TX_WTHRESH 0  /**< Default values of TX write-back threshold
>>>> reg. */
>>>> +
>>>> +#define MAX_PKT_BURST 32
>>>> +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
>>>> +#define RTE_TEST_RX_DESC_DEFAULT 128
>>>> +#define RTE_TEST_TX_DESC_DEFAULT 512
>>>> +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
>>>> +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
>>>> +
>>>> +static const struct rte_eth_conf port_conf = {
>>>> +       .rxmode = {
>>>> +               .split_hdr_size = 0,
>>>> +               .header_split   = 0, /**< Header Split disabled */
>>>> +               .hw_ip_checksum = 0, /**< IP checksum offload disabled
>>>> */
>>>> +               .hw_vlan_filter = 0, /**< VLAN filtering disabled */
>>>> +               .jumbo_frame    = 0, /**< Jumbo Frame Support disabled
>>>> */
>>>> +               .hw_strip_crc   = 0, /**< CRC stripped by hardware */
>>>> +       },
>>>> +       .txmode = {
>>>> +               .mq_mode = ETH_MQ_TX_NONE,
>>>> +       },
>>>> +};
>>>> +
>>>> +static const struct rte_eth_rxconf rx_conf = {
>>>> +       .rx_thresh = {
>>>> +               .pthresh = RX_PTHRESH,
>>>> +               .hthresh = RX_HTHRESH,
>>>> +               .wthresh = RX_WTHRESH,
>>>> +       },
>>>> +};
>>>> +
>>>> +static const struct rte_eth_txconf tx_conf = {
>>>> +       .tx_thresh = {
>>>> +               .pthresh = TX_PTHRESH,
>>>> +               .hthresh = TX_HTHRESH,
>>>> +               .wthresh = TX_WTHRESH,
>>>> +       },
>>>> +       .tx_free_thresh = 0, /* Use PMD default values */
>>>> +       .tx_rs_thresh = 0, /* Use PMD default values */
>>>> +       /*
>>>> +        * As the example won't handle mult-segments and offload cases,
>>>> +        * set the flag by default.
>>>> +        */
>>>> +       .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
>>>> ETH_TXQ_FLAGS_NOOFFLOADS,
>>>> +};
>>>> +
>>>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
>>>> +               odp_buffer_pool_t pool)
>>>> +{
>>>> +       ODP_DBG("setup_pkt_dpdk\n");
>>>> +
>>>> +       static struct ether_addr eth_addr[RTE_MAX_ETHPORTS];
>>>> +       uint8_t portid = 0;
>>>> +       uint16_t queueid = 0;
>>>> +       int ret;
>>>> +       printf("vincent netdev: %s\n", netdev);
>>>> +       printf("vincent pool: %lx\n", pool);
>>>> +
>>>> +       portid = atoi(netdev);
>>>> +       pkt_dpdk->portid = portid;
>>>> +       pkt_dpdk->queueid = queueid;
>>>> +       pkt_dpdk->pool = pool;
>>>> +       printf("vincent portid: %u\n", portid);
>>>> +
>>>> +       fflush(stdout);
>>>> +       ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
>>>> +       if (ret < 0)
>>>> +               ODP_ERR("Cannot configure device: err=%d, port=%u\n",
>>>> +                       ret, (unsigned) portid);
>>>> +
>>>> +       rte_eth_macaddr_get(portid, &eth_addr[portid]);
>>>> +       ODP_DBG("Port %u, MAC address:
>>>> %02X:%02X:%02X:%02X:%02X:%02X\n\n",
>>>> +               (unsigned) portid,
>>>> +               eth_addr[portid].addr_bytes[0],
>>>> +               eth_addr[portid].addr_bytes[1],
>>>> +               eth_addr[portid].addr_bytes[2],
>>>> +               eth_addr[portid].addr_bytes[3],
>>>> +               eth_addr[portid].addr_bytes[4],
>>>> +               eth_addr[portid].addr_bytes[5]);
>>>> +
>>>> +       /* init one RX queue on each port */
>>>> +       fflush(stdout);
>>>> +       ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
>>>> +                                    rte_eth_dev_socket_id(portid),
>>>> &rx_conf,
>>>> +                                    (struct rte_mempool *)pool);
>>>> +       if (ret < 0)
>>>> +               ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n",
>>>> +                       ret, (unsigned) portid);
>>>> +       ODP_DBG("dpdk rx queue setup done\n");
>>>> +
>>>> +       /* init one TX queue on each port */
>>>> +       fflush(stdout);
>>>> +       ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
>>>> +                       rte_eth_dev_socket_id(portid), &tx_conf);
>>>> +       if (ret < 0)
>>>> +               ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n",
>>>> +                       ret, (unsigned) portid);
>>>> +       ODP_DBG("dpdk tx queue setup done\n");
>>>> +
>>>> +       /* Start device */
>>>> +       ret = rte_eth_dev_start(portid);
>>>> +       if (ret < 0)
>>>> +               ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n",
>>>> +                       ret, (unsigned) portid);
>>>> +       ODP_DBG("dpdk setup done\n\n");
>>>> +
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk)
>>>> +{
>>>> +       ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t
>>>> pkt_table[],
>>>> +               unsigned len)
>>>> +{
>>>> +       return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid,
>>>> +                               (uint16_t)pkt_dpdk->queueid,
>>>> +                               (struct rte_mbuf **)pkt_table,
>>>> (uint16_t)len);
>>>> +}
>>>> +
>>>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t
>>>> pkt_table[],
>>>> +               unsigned len)
>>>> +{
>>>> +       return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid,
>>>> +                               (uint16_t)pkt_dpdk->queueid,
>>>> +                               (struct rte_mbuf **)pkt_table,
>>>> (uint16_t)len);
>>>> +}
>>>> diff --git a/platform/linux-dpdk/source/odp_packet_io.c
>>>> b/platform/linux-dpdk/source/odp_packet_io.c
>>>> new file mode 100644
>>>> index 0000000..abea0ec
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/source/odp_packet_io.c
>>>> @@ -0,0 +1,561 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#include <odp_packet_io.h>
>>>> +#include <odp_packet_io_internal.h>
>>>> +#include <odp_packet_io_queue.h>
>>>> +#include <odp_packet.h>
>>>> +#include <odp_packet_internal.h>
>>>> +#include <odp_internal.h>
>>>> +#include <odp_spinlock.h>
>>>> +#include <odp_shared_memory.h>
>>>> +#include <odp_packet_socket.h>
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +#include <odp_packet_netmap.h>
>>>> +#endif
>>>> +#include <odp_hints.h>
>>>> +#include <odp_config.h>
>>>> +#include <odp_queue_internal.h>
>>>> +#include <odp_schedule_internal.h>
>>>> +#include <odp_debug.h>
>>>> +
>>>> +#include <odp_pktio_socket.h>
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +#include <odp_pktio_netmap.h>
>>>> +#endif
>>>> +
>>>> +#include <string.h>
>>>> +
>>>> +typedef struct {
>>>> +       pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
>>>> +} pktio_table_t;
>>>> +
>>>> +static pktio_table_t *pktio_tbl;
>>>> +
>>>> +
>>>> +static pktio_entry_t *get_entry(odp_pktio_t id)
>>>> +{
>>>> +       if (odp_unlikely(id == ODP_PKTIO_INVALID ||
>>>> +                        id > ODP_CONFIG_PKTIO_ENTRIES))
>>>> +               return NULL;
>>>> +
>>>> +       return &pktio_tbl->entries[id - 1];
>>>> +}
>>>> +
>>>> +int odp_pktio_init_global(void)
>>>> +{
>>>> +       char name[ODP_QUEUE_NAME_LEN];
>>>> +       pktio_entry_t *pktio_entry;
>>>> +       queue_entry_t *queue_entry;
>>>> +       odp_queue_t qid;
>>>> +       int id;
>>>> +
>>>> +       pktio_tbl = odp_shm_reserve("odp_pktio_entries",
>>>> +                                   sizeof(pktio_table_t),
>>>> +                                   sizeof(pktio_entry_t));
>>>> +       if (pktio_tbl == NULL)
>>>> +               return -1;
>>>> +
>>>> +       memset(pktio_tbl, 0, sizeof(pktio_table_t));
>>>> +
>>>> +       for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
>>>> +               pktio_entry = get_entry(id);
>>>> +
>>>> +               odp_spinlock_init(&pktio_entry->s.lock);
>>>> +
>>>> +               /* Create a default output queue for each pktio
>>>> resource */
>>>> +               snprintf(name, sizeof(name), "%i-pktio_outq_default",
>>>> (int)id);
>>>> +               name[ODP_QUEUE_NAME_LEN-1] = '\0';
>>>> +
>>>> +               qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT,
>>>> NULL);
>>>> +               if (qid == ODP_QUEUE_INVALID)
>>>> +                       return -1;
>>>> +               pktio_entry->s.outq_default = qid;
>>>> +
>>>> +               queue_entry = queue_to_qentry(qid);
>>>> +               queue_entry->s.pktout = id;
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int odp_pktio_init_local(void)
>>>> +{
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int is_free(pktio_entry_t *entry)
>>>> +{
>>>> +       return (entry->s.taken == 0);
>>>> +}
>>>> +
>>>> +static void set_free(pktio_entry_t *entry)
>>>> +{
>>>> +       entry->s.taken = 0;
>>>> +}
>>>> +
>>>> +static void set_taken(pktio_entry_t *entry)
>>>> +{
>>>> +       entry->s.taken = 1;
>>>> +}
>>>> +
>>>> +static void lock_entry(pktio_entry_t *entry)
>>>> +{
>>>> +       odp_spinlock_lock(&entry->s.lock);
>>>> +}
>>>> +
>>>> +static void unlock_entry(pktio_entry_t *entry)
>>>> +{
>>>> +       odp_spinlock_unlock(&entry->s.lock);
>>>> +}
>>>> +
>>>> +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t
>>>> *params)
>>>> +{
>>>> +       set_taken(entry);
>>>> +       entry->s.inq_default = ODP_QUEUE_INVALID;
>>>> +       switch (params->type) {
>>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>>> +               memset(&entry->s.pkt_sock, 0,
>>>> sizeof(entry->s.pkt_sock));
>>>> +               memset(&entry->s.pkt_sock_mmap, 0,
>>>> +                      sizeof(entry->s.pkt_sock_mmap));
>>>> +               break;
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>>> +               memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm));
>>>> +               break;
>>>> +#endif
>>>> +       case ODP_PKTIO_TYPE_DPDK:
>>>> +               memset(&entry->s.pkt_dpdk, 0,
>>>> sizeof(entry->s.pkt_dpdk));
>>>> +               break;
>>>> +       default:
>>>> +               ODP_ERR("Packet I/O type not supported. Please
>>>> recompile\n");
>>>> +               break;
>>>> +       }
>>>> +       /* Save pktio parameters, type is the most useful */
>>>> +       memcpy(&entry->s.params, params, sizeof(*params));
>>>> +}
>>>> +
>>>> +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
>>>> +{
>>>> +       odp_pktio_t id;
>>>> +       pktio_entry_t *entry;
>>>> +       int i;
>>>> +
>>>> +       for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
>>>> +               entry = &pktio_tbl->entries[i];
>>>> +               if (is_free(entry)) {
>>>> +                       lock_entry(entry);
>>>> +                       if (is_free(entry)) {
>>>> +                               init_pktio_entry(entry, params);
>>>> +                               id = i + 1;
>>>> +                               return id; /* return with entry locked!
>>>> */
>>>> +                       }
>>>> +                       unlock_entry(entry);
>>>> +               }
>>>> +       }
>>>> +
>>>> +       return ODP_PKTIO_INVALID;
>>>> +}
>>>> +
>>>> +static int free_pktio_entry(odp_pktio_t id)
>>>> +{
>>>> +       pktio_entry_t *entry = get_entry(id);
>>>> +
>>>> +       if (entry == NULL)
>>>> +               return -1;
>>>> +
>>>> +       set_free(entry);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
>>>> +                          odp_pktio_params_t *params)
>>>> +{
>>>> +       odp_pktio_t id;
>>>> +       pktio_entry_t *pktio_entry;
>>>> +       int res;
>>>> +
>>>> +       if (params == NULL) {
>>>> +               ODP_ERR("Invalid pktio params\n");
>>>> +               return ODP_PKTIO_INVALID;
>>>> +       }
>>>> +
>>>> +       switch (params->type) {
>>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>>> +               ODP_DBG("Allocating socket pktio\n");
>>>> +               break;
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>>> +               ODP_DBG("Allocating netmap pktio\n");
>>>> +               break;
>>>> +#endif
>>>> +       case ODP_PKTIO_TYPE_DPDK:
>>>> +               ODP_DBG("Allocating dpdk pktio\n");
>>>> +               break;
>>>> +       default:
>>>> +               ODP_ERR("Invalid pktio type: %02x\n", params->type);
>>>> +               return ODP_PKTIO_INVALID;
>>>> +       }
>>>> +
>>>> +       id = alloc_lock_pktio_entry(params);
>>>> +       if (id == ODP_PKTIO_INVALID) {
>>>> +               ODP_ERR("No resources available.\n");
>>>> +               return ODP_PKTIO_INVALID;
>>>> +       }
>>>> +       /* if successful, alloc_pktio_entry() returns with the entry
>>>> locked */
>>>> +
>>>> +       pktio_entry = get_entry(id);
>>>> +
>>>> +       switch (params->type) {
>>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>>> +               res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev,
>>>> pool);
>>>> +               if (res == -1) {
>>>> +                       close_pkt_sock(&pktio_entry->s.pkt_sock);
>>>> +                       free_pktio_entry(id);
>>>> +                       id = ODP_PKTIO_INVALID;
>>>> +               }
>>>> +               break;
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>>> +               res =
>>>> setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, dev,
>>>> +                               pool, params->sock_params.fanout);
>>>> +               if (res == -1) {
>>>> +
>>>> close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap);
>>>> +                       free_pktio_entry(id);
>>>> +                       id = ODP_PKTIO_INVALID;
>>>> +               }
>>>> +               break;
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>>> +
>>>> +               res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev,
>>>> +                               pool, &params->nm_params);
>>>> +               if (res == -1) {
>>>> +                       close_pkt_netmap(&pktio_entry->s.pkt_nm);
>>>> +                       free_pktio_entry(id);
>>>> +                       id = ODP_PKTIO_INVALID;
>>>> +               }
>>>> +               break;
>>>> +#endif
>>>> +       case ODP_PKTIO_TYPE_DPDK:
>>>> +               res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev,
>>>> pool);
>>>> +               if (res == -1) {
>>>> +                       close_pkt_dpdk(&pktio_entry->s.pkt_dpdk);
>>>> +                       free_pktio_entry(id);
>>>> +                       id = ODP_PKTIO_INVALID;
>>>> +               }
>>>> +               break;
>>>> +       default:
>>>> +               free_pktio_entry(id);
>>>> +               id = ODP_PKTIO_INVALID;
>>>> +               ODP_ERR("Invalid pktio type. Please recompile.\n");
>>>> +               break;
>>>> +       }
>>>> +
>>>> +       unlock_entry(pktio_entry);
>>>> +       return id;
>>>> +}
>>>> +
>>>> +int odp_pktio_close(odp_pktio_t id)
>>>> +{
>>>> +       pktio_entry_t *entry;
>>>> +       int res = -1;
>>>> +
>>>> +       entry = get_entry(id);
>>>> +       if (entry == NULL)
>>>> +               return -1;
>>>> +
>>>> +       lock_entry(entry);
>>>> +       if (!is_free(entry)) {
>>>> +               switch (entry->s.params.type) {
>>>> +               case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>>> +               case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>>> +                       res  = close_pkt_sock(&entry->s.pkt_sock);
>>>> +                       break;
>>>> +               case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>>> +                       res  =
>>>> close_pkt_sock_mmap(&entry->s.pkt_sock_mmap);
>>>> +                       break;
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +               case ODP_PKTIO_TYPE_NETMAP:
>>>> +                       res  = close_pkt_netmap(&entry->s.pkt_nm);
>>>> +                       break;
>>>> +#endif
>>>> +               case ODP_PKTIO_TYPE_DPDK:
>>>> +                       res  = close_pkt_dpdk(&entry->s.pkt_dpdk);
>>>> +                       break;
>>>> +               default:
>>>> +                       break;
>>>> +               res |= free_pktio_entry(id);
>>>> +               }
>>>> +       }
>>>> +       unlock_entry(entry);
>>>> +
>>>> +       if (res != 0)
>>>> +               return -1;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio)
>>>> +{
>>>> +       odp_packet_hdr(pkt)->input = pktio;
>>>> +}
>>>> +
>>>> +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt)
>>>> +{
>>>> +       return odp_packet_hdr(pkt)->input;
>>>> +}
>>>> +
>>>> +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned
>>>> len)
>>>> +{
>>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>>> +       int pkts;
>>>> +       int i;
>>>> +
>>>> +       if (pktio_entry == NULL)
>>>> +               return -1;
>>>> +
>>>> +       lock_entry(pktio_entry);
>>>> +       switch (pktio_entry->s.params.type) {
>>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>>> +               pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock,
>>>> +                               pkt_table, len);
>>>> +               break;
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>>> +               pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
>>>> +                               pkt_table, len);
>>>> +               break;
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>>> +               pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>>>> +                               pkt_table, len);
>>>> +               break;
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>>> +               pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm,
>>>> pkt_table, len);
>>>> +               break;
>>>> +#endif
>>>> +       case ODP_PKTIO_TYPE_DPDK:
>>>> +               pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk,
>>>> pkt_table, len);
>>>> +               break;
>>>> +       default:
>>>> +               pkts = -1;
>>>> +               break;
>>>> +       }
>>>> +
>>>> +       unlock_entry(pktio_entry);
>>>> +       if (pkts < 0)
>>>> +               return pkts;
>>>> +
>>>> +       for (i = 0; i < pkts; ++i)
>>>> +               odp_pktio_set_input(pkt_table[i], id);
>>>> +
>>>> +       return pkts;
>>>> +}
>>>> +
>>>> +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned
>>>> len)
>>>> +{
>>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>>> +       int pkts;
>>>> +
>>>> +       if (pktio_entry == NULL)
>>>> +               return -1;
>>>> +
>>>> +       lock_entry(pktio_entry);
>>>> +       switch (pktio_entry->s.params.type) {
>>>> +       case ODP_PKTIO_TYPE_SOCKET_BASIC:
>>>> +               pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock,
>>>> +                               pkt_table, len);
>>>> +               break;
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMSG:
>>>> +               pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
>>>> +                               pkt_table, len);
>>>> +               break;
>>>> +       case ODP_PKTIO_TYPE_SOCKET_MMAP:
>>>> +               pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
>>>> +                               pkt_table, len);
>>>> +               break;
>>>> +#ifdef ODP_HAVE_NETMAP
>>>> +       case ODP_PKTIO_TYPE_NETMAP:
>>>> +               pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm,
>>>> +                               pkt_table, len);
>>>> +               break;
>>>> +#endif
>>>> +       case ODP_PKTIO_TYPE_DPDK:
>>>> +               pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk,
>>>> +                               pkt_table, len);
>>>> +               break;
>>>> +       default:
>>>> +               pkts = -1;
>>>> +       }
>>>> +       unlock_entry(pktio_entry);
>>>> +
>>>> +       return pkts;
>>>> +}
>>>> +
>>>> +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue)
>>>> +{
>>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>>> +       queue_entry_t *qentry = queue_to_qentry(queue);
>>>> +
>>>> +       if (pktio_entry == NULL || qentry == NULL)
>>>> +               return -1;
>>>> +
>>>> +       if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN)
>>>> +               return -1;
>>>> +
>>>> +       lock_entry(pktio_entry);
>>>> +       pktio_entry->s.inq_default = queue;
>>>> +       unlock_entry(pktio_entry);
>>>> +
>>>> +       queue_lock(qentry);
>>>> +       qentry->s.pktin = id;
>>>> +       qentry->s.status = QUEUE_STATUS_SCHED;
>>>> +       queue_unlock(qentry);
>>>> +
>>>> +       odp_schedule_queue(queue, qentry->s.param.sched.prio);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int odp_pktio_inq_remdef(odp_pktio_t id)
>>>> +{
>>>> +       return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID);
>>>> +}
>>>> +
>>>> +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
>>>> +{
>>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>>> +
>>>> +       if (pktio_entry == NULL)
>>>> +               return ODP_QUEUE_INVALID;
>>>> +
>>>> +       return pktio_entry->s.inq_default;
>>>> +}
>>>> +
>>>> +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
>>>> +{
>>>> +       pktio_entry_t *pktio_entry = get_entry(id);
>>>> +
>>>> +       if (pktio_entry == NULL)
>>>> +               return ODP_QUEUE_INVALID;
>>>> +
>>>> +       return pktio_entry->s.outq_default;
>>>> +}
>>>> +
>>>> +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
>>>> +{
>>>> +       odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t)
>>>> buf_hdr);
>>>> +       int len = 1;
>>>> +       int nbr;
>>>> +
>>>> +       nbr = odp_pktio_send(qentry->s.pktout, &pkt, len);
>>>> +       return (nbr == len ? 0 : -1);
>>>> +}
>>>> +
>>>> +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry)
>>>> +{
>>>> +       (void)qentry;
>>>> +       return NULL;
>>>> +}
>>>> +
>>>> +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t
>>>> *buf_hdr[],
>>>> +                    int num)
>>>> +{
>>>> +       odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>>>> +       int nbr;
>>>> +       int i;
>>>> +
>>>> +       for (i = 0; i < num; ++i)
>>>> +               pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t)
>>>> buf_hdr[i]);
>>>> +
>>>> +       nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num);
>>>> +       return (nbr == num ? 0 : -1);
>>>> +}
>>>> +
>>>> +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t
>>>> *buf_hdr[],
>>>> +                    int num)
>>>> +{
>>>> +       (void)qentry;
>>>> +       (void)buf_hdr;
>>>> +       (void)num;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
>>>> +{
>>>> +       /* Use default action */
>>>> +       return queue_enq(qentry, buf_hdr);
>>>> +}
>>>> +
>>>> +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
>>>> +{
>>>> +       odp_buffer_hdr_t *buf_hdr;
>>>> +
>>>> +       buf_hdr = queue_deq(qentry);
>>>> +
>>>> +       if (buf_hdr == NULL) {
>>>> +               odp_packet_t pkt;
>>>> +               odp_buffer_t buf;
>>>> +               odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>>>> +               odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
>>>> +               int pkts, i, j;
>>>> +
>>>> +               pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
>>>> +                                     QUEUE_MULTI_MAX);
>>>> +
>>>> +               if (pkts > 0) {
>>>> +                       pkt = pkt_tbl[0];
>>>> +                       buf = odp_buffer_from_packet(pkt);
>>>> +                       buf_hdr = odp_buf_to_hdr(buf);
>>>> +
>>>> +                       for (i = 1, j = 0; i < pkts; ++i) {
>>>> +                               buf =
>>>> odp_buffer_from_packet(pkt_tbl[i]);
>>>> +                               tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf);
>>>> +                       }
>>>> +                       queue_enq_multi(qentry, tmp_hdr_tbl, j);
>>>> +               }
>>>> +       }
>>>> +
>>>> +       return buf_hdr;
>>>> +}
>>>> +
>>>> +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t
>>>> *buf_hdr[], int num)
>>>> +{
>>>> +       /* Use default action */
>>>> +       return queue_enq_multi(qentry, buf_hdr, num);
>>>> +}
>>>> +
>>>> +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t
>>>> *buf_hdr[], int num)
>>>> +{
>>>> +       int nbr;
>>>> +
>>>> +       nbr = queue_deq_multi(qentry, buf_hdr, num);
>>>> +
>>>> +       if (nbr < num) {
>>>> +               odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
>>>> +               odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
>>>> +               odp_buffer_t buf;
>>>> +               int pkts, i;
>>>> +
>>>> +               pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
>>>> +                                     QUEUE_MULTI_MAX);
>>>> +               if (pkts > 0) {
>>>> +                       for (i = 0; i < pkts; ++i) {
>>>> +                               buf =
>>>> odp_buffer_from_packet(pkt_tbl[i]);
>>>> +                               tmp_hdr_tbl[i] = odp_buf_to_hdr(buf);
>>>> +                       }
>>>> +                       queue_enq_multi(qentry, tmp_hdr_tbl, pkts);
>>>> +               }
>>>> +       }
>>>> +
>>>> +       return nbr;
>>>> +}
>>>> diff --git a/platform/linux-dpdk/source/odp_queue.c
>>>> b/platform/linux-dpdk/source/odp_queue.c
>>>> new file mode 100644
>>>> index 0000000..554b8ea
>>>> --- /dev/null
>>>> +++ b/platform/linux-dpdk/source/odp_queue.c
>>>> @@ -0,0 +1,435 @@
>>>> +/* Copyright (c) 2013, Linaro Limited
>>>> + * All rights reserved.
>>>> + *
>>>> + * SPDX-License-Identifier:     BSD-3-Clause
>>>> + */
>>>> +
>>>> +#include <odp_queue.h>
>>>> +#include <odp_queue_internal.h>
>>>> +#include <odp_std_types.h>
>>>> +#include <odp_align.h>
>>>> +#include <odp_buffer.h>
>>>> +#include <odp_buffer_internal.h>
>>>> +#include <odp_buffer_pool_internal.h>
>>>> +#include <odp_internal.h>
>>>> +#include <odp_shared_memory.h>
>>>> +#include <odp_schedule_internal.h>
>>>> +#include <odp_config.h>
>>>> +#include <odp_packet_io_internal.h>
>>>> +#include <odp_packet_io_queue.h>
>>>> +#include <odp_debug.h>
>>>> +#include <odp_hints.h>
>>>> +
>>>> +#ifdef USE_TICKETLOCK
>>>> +#include <odp_ticketlock.h>
>>>> +#define LOCK(a)      odp_ticketlock_lock(a)
>>>> +#define UNLOCK(a)    odp_ticketlock_unlock(a)
>>>> +#define LOCK_INIT(a) odp_ticketlock_init(a)
>>>> +#else
>>>> +#include <odp_spinlock.h>
>>>> +#define LOCK(a)      odp_spinlock_lock(a)
>>>> +#define UNLOCK(a)    odp_spinlock_unlock(a)
>>>> +#define LOCK_INIT(a) odp_spinlock_init(a)
>>>> +#endif
>>>> +
>>>> +#include <string.h>
>>>> +
>>>> +
>>>> +typedef struct queue_table_t {
>>>> +       queue_entry_t  queue[ODP_CONFIG_QUEUES];
>>>> +} queue_table_t;
>>>> +
>>>> +static queue_table_t *queue_tbl;
>>>> +
>>>> +
>>>> +queue_entry_t *get_qentry(uint32_t queue_id)
>>>> +{
>>>> +       return &queue_tbl->queue[queue_id];
>>>> +}
>>>> +
>>>> +static void queue_init(queue_entry_t *queue, const char *name,
>>>> +                      odp_queue_type_t type, odp_queue_param_t *param)
>>>> +{
>>>> +       strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1);
>>>> +       queue->s.type = type;
>>>> +
>>>> +       if (param) {
>>>> +               memcpy(&queue->s.param, param,
>>>> sizeof(odp_queue_param_t));
>>>> +       } else {
>>>> +               /* Defaults */
>>>> +               memset(&queue->s.param, 0, sizeof(odp_queue_param_t));
>>>> +               queue->s.param.sched.prio  = ODP_SCHED_PRIO_DEFAULT;
>>>> +               queue->s.param.sched.sync  = ODP_SCHED_SYNC_DEFAULT;
>>>> +               queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT;
>>>> +       }
>>>> +
>>>> +       switch (type) {
>>>> +       case ODP_QUEUE_TYPE_PKTIN:
>>>> +               queue->s.enqueue = pktin_enqueue;
>>>> +               queue->s.dequeue = pktin_dequeue;
>>>> +               queue->s.enqueue_multi = pktin_enq_multi;
>>>> +               queue->s.dequeue_multi = pktin_deq_multi;
>>>> +               break;
>>>> +       case ODP_QUEUE_TYPE_PKTOUT:
>>>> +               queue->s.enqueue = pktout_enqueue;
>>>> +               queue->s.dequeue = pktout_dequeue;
>>>> +               queue->s.enqueue_multi = pktout_enq_multi;
>>>> +               queue->s.dequeue_multi = pktout_deq_multi;
>>>> +               break;
>>>> +       default:
>>>> +               queue->s.enqueue = queue_enq;
>>>> +               queue->s.dequeue = queue_deq;
>>>> +               queue->s.enqueue_multi = queue_enq_multi;
>>>> +               queue->s.dequeue_multi = queue_deq_multi;
>>>> +               break;
>>>> +       }
>>>> +
>>>> +       queue->s.head = NULL;
>>>> +       queue->s.tail = NULL;
>>>> +       queue->s.sched_buf = ODP_BUFFER_INVALID;
>>>> +}
>>>> +
>>>> +
>>>> +int odp_queue_init_global(void)
>>>> +{
>>>> +       uint32_t i;
>>>> +
>>>> +       ODP_DBG("Queue init ... ");
>>>> +
>>>> +       queue_tbl = odp_shm_reserve("odp_queues",
>>>> +                                   sizeof(queue_table_t),
>>>> +                                   sizeof(queue_entry_t));
>>>> +
>>>> +       if (queue_tbl == NULL)
>>>> +               return -1;
>>>> +
>>>> +       memset(queue_tbl, 0, sizeof(queue_table_t));
>>>> +
>>>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>>>> +               /* init locks */
>>>> +               queue_entry_t *queue = get_qentry(i);
>>>> +               LOCK_INIT(&queue->s.lock);
>>>> +               queue->s.handle = queue_from_id(i);
>>>> +       }
>>>> +
>>>> +       ODP_DBG("done\n");
>>>> +       ODP_DBG("Queue init global\n");
>>>> +       ODP_DBG("  struct queue_entry_s size %zu\n",
>>>> +               sizeof(struct queue_entry_s));
>>>> +       ODP_DBG("  queue_entry_t size        %zu\n",
>>>> +               sizeof(queue_entry_t));
>>>> +       ODP_DBG("\n");
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +odp_queue_type_t odp_queue_type(odp_queue_t handle)
>>>> +{
>>>> +       queue_entry_t *queue;
>>>> +
>>>> +       queue = queue_to_qentry(handle);
>>>> +
>>>> +       return queue->s.type;
>>>> +}
>>>> +
>>>> +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle)
>>>> +{
>>>> +       queue_entry_t *queue;
>>>> +
>>>> +       queue = queue_to_qentry(handle);
>>>> +
>>>> +       return queue->s.param.sched.sync;
>>>> +}
>>>> +
>>>> +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
>>>> +                            odp_queue_param_t *param)
>>>> +{
>>>> +       uint32_t i;
>>>> +       queue_entry_t *queue;
>>>> +       odp_queue_t handle = ODP_QUEUE_INVALID;
>>>> +
>>>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>>>> +               queue = &queue_tbl->queue[i];
>>>> +
>>>> +               if (queue->s.status != QUEUE_STATUS_FREE)
>>>> +                       continue;
>>>> +
>>>> +               LOCK(&queue->s.lock);
>>>> +               if (queue->s.status == QUEUE_STATUS_FREE) {
>>>> +                       queue_init(queue, name, type, param);
>>>> +
>>>> +                       if (type == ODP_QUEUE_TYPE_SCHED ||
>>>> +                           type == ODP_QUEUE_TYPE_PKTIN)
>>>> +                               queue->s.status = QUEUE_STATUS_NOTSCHED;
>>>> +                       else
>>>> +                               queue->s.status = QUEUE_STATUS_READY;
>>>> +
>>>> +                       handle = queue->s.handle;
>>>> +                       UNLOCK(&queue->s.lock);
>>>> +                       break;
>>>> +               }
>>>> +               UNLOCK(&queue->s.lock);
>>>> +       }
>>>> +
>>>> +       if (handle != ODP_QUEUE_INVALID &&
>>>> +           (type == ODP_QUEUE_TYPE_SCHED || type ==
>>>> ODP_QUEUE_TYPE_PKTIN)) {
>>>> +               odp_buffer_t buf;
>>>> +
>>>> +               buf = odp_schedule_buffer_alloc(handle);
>>>> +               if (buf == ODP_BUFFER_INVALID) {
>>>> +                       ODP_ERR("queue_init: sched buf alloc failed\n");
>>>> +                       return ODP_QUEUE_INVALID;
>>>> +               }
>>>> +
>>>> +               queue->s.sched_buf = buf;
>>>> +               odp_schedule_mask_set(handle,
>>>> queue->s.param.sched.prio);
>>>> +       }
>>>> +
>>>> +       return handle;
>>>> +}
>>>> +
>>>> +
>>>> +odp_buffer_t queue_sched_buf(odp_queue_t handle)
>>>> +{
>>>> +       queue_entry_t *queue;
>>>> +       queue = queue_to_qentry(handle);
>>>> +
>>>> +       return queue->s.sched_buf;
>>>> +}
>>>> +
>>>> +
>>>> +int queue_sched_atomic(odp_queue_t handle)
>>>> +{
>>>> +       queue_entry_t *queue;
>>>> +       queue = queue_to_qentry(handle);
>>>> +
>>>> +       return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC;
>>>> +}
>>>> +
>>>> +
>>>> +odp_queue_t odp_queue_lookup(const char *name)
>>>> +{
>>>> +       uint32_t i;
>>>> +
>>>> +       for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
>>>> +               queue_entry_t *queue = &queue_tbl->queue[i];
>>>> +
>>>> +               if (queue->s.status == QUEUE_STATUS_FREE)
>>>> +                       continue;
>>>> +
>>>> +               LOCK(&queue->s.lock);
>>>> +               if (strcmp(name, queue->s.name) == 0) {
>>>> +                       /* found it */
>>>> +                       UNLOCK(&queue->s.lock);
>>>> +                       return queue->s.handle;
>>>> +               }
>>>> +               UNLOCK(&queue->s.lock);
>>>> +       }
>>>> +
>>>> +       return ODP_QUEUE_INVALID;
>>>> +}
>>>> +
>>>> +
>>>> +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
>>>> +{
>>>> +       int sched = 0;
>>>> +
>>>> +       LOCK(&queue->s.lock);
>>>> +       if (queue->s.head == NULL) {
>>>> +               /* Empty queue */
>>>> +               queue->s.head = buf_hdr;
>>>> +               queue->s.tail = buf_hdr;
>>>> +               buf_hdr->pkt.next = NULL;
>>>> +       } else {
>>>> +               queue->s.tail->pkt.next = buf_hdr;
>>>> +               queue->s.tail = buf_hdr;
>>>> +               buf_hdr->pkt.next = NULL;
>>>> +       }
>>>> +
>>>> +       if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
>>>> +               queue->s.status = QUEUE_STATUS_SCHED;
>>>> +               sched = 1; /* retval: schedule queue */
>>>> +       }
>>>> +       UNLOCK(&queue->s.lock);
>>>> +
>>>> +       /* Add queue to scheduling */
>>>> +       if (sched == 1)
>>>> +               odp_schedule_queue(queue->s.handle,
>>>> queue->s.param.sched.prio);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +
>>>> +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
>>>> int num)
>>>> +{
>>>> +       int sched = 0;
>>>> +       int i;
>>>> +       odp_buffer_hdr_t *tail;
>>>> +
>>>> +       for (i = 0; i < num - 1; i++)
>>>> +               buf_hdr[i]->pkt.next = buf_hdr[i+1];
>>>> +
>>>> +       tail = buf_hdr[num-1];
>>>> +       buf_hdr[num-1]->pkt.next = NULL;
>>>> +
>>>> +       LOCK(&queue->s.lock);
>>>> +       /* Empty queue */
>>>> +       if (queue->s.head == NULL)
>>>> +               queue->s.head = buf_hdr[0];
>>>> +       else
>>>> +               queue->s.tail->pkt.next = buf_hdr[0];
>>>> +
>>>> +       queue->s.tail = tail;
>>>> +
>>>> +       if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
>>>> +               queue->s.status = QUEUE_STATUS_SCHED;
>>>> +               sched = 1; /* retval: schedule queue */
>>>> +       }
>>>> +       UNLOCK(&queue->s.lock);
>>>> +
>>>> +       /* Add queue to scheduling */
>>>> +       if (sched == 1)
>>>> +               odp_schedule_queue(queue->s.handle,
>>>> queue->s.param.sched.prio);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +
>>>> +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int
>>>> num)
>>>> +{
>>>> +       odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
>>>> +       queue_entry_t *queue;
>>>> +       int i;
>>>> +
>>>> +       if (num > QUEUE_MULTI_MAX)
>>>> +               num = QUEUE_MULTI_MAX;
>>>> +
>>>> +       queue = queue_to_qentry(handle);
>>>> +
>>>> +       for (i = 0; i < num; i++)
>>>> +               buf_hdr[i] = odp_buf_to_hdr(buf[i]);
>>>> +
>>>> +       return queue->s.enqueue_multi(queue, buf_hdr, num);
>>>> +}
>>>> +
>>>> +
>>>> +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf)
>>>> +{
>>>> +       odp_buffer_hdr_t *buf_hdr;
>>>> +       queue_entry_t *queue;
>>>> +
>>>> +       queue   = queue_to_qentry(handle);
>>>> +       buf_hdr = odp_buf_to_hdr(buf);
>>>> +
>>>> +       return queue->s.enqueue(queue, buf_hdr);
>>>> +}
>>>> +
>>>> +
>>>> +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
>>>> +{
>>>> +       odp_buffer_hdr_t *buf_hdr = NULL;
>>>> +
>>>> +       LOCK(&queue->s.lock);
>>>> +
>>>> +       if (queue->s.head == NULL) {
>>>> +               /* Already empty queue */
>>>> +               if (queue->s.status == QUEUE_STATUS_SCHED &&
>>>> +                   queue->s.type != ODP_QUEUE_TYPE_PKTIN)
>>>> +                       queue->s.status = QUEUE_STATUS_NOTSCHED;
>>>> +       } else {
>>>> +               buf_hdr       = queue->s.head;
>>>> +               queue->s.head = buf_hdr->pkt.next;
>>>> +               buf_hdr->pkt.next = NULL;
>>>> +
>>>> +               if (queue->s.head == NULL) {
>>>> +                       /* Queue is now empty */
>>>> +                       queue->s.tail = NULL;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       UNLOCK(&queue->s.lock);
>>>> +
>>>> +       return buf_hdr;
>>>> +}
>>>> +
>>>> +
>>>> +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
>>>> int num)
>>>> +{
>>>> +       int i = 0;
>>>> +
>>>> +       LOCK(&queue->s.lock);
>>>> +
>>>> +       if (queue->s.head == NULL) {
>>>> +               /* Already empty queue */
>>>> +               if (queue->s.status == QUEUE_STATUS_SCHED &&
>>>> +                   queue->s.type != ODP_QUEUE_TYPE_PKTIN)
>>>> +                       queue->s.status = QUEUE_STATUS_NOTSCHED;
>>>> +       } else {
>>>> +               odp_buffer_hdr_t *hdr = queue->s.head;
>>>> +
>>>> +               for (; i < num && hdr; i++) {
>>>> +                       buf_hdr[i]       = hdr;
>>>> +                       /* odp_prefetch(hdr->addr); */
>>>> +                       hdr              = hdr->pkt.next;
>>>> +                       buf_hdr[i]->pkt.next = NULL;
>>>> +               }
>>>> +
>>>> +               queue->s.head = hdr;
>>>> +
>>>> +               if (hdr == NULL) {
>>>> +                       /* Queue is now empty */
>>>> +                       queue->s.tail = NULL;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       UNLOCK(&queue->s.lock);
>>>> +
>>>> +       return i;
>>>> +}
>>>> +
>>>> +
>>>> +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int
>>>> num)
>>>> +{
>>>> +       queue_entry_t *queue;
>>>> +       odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
>>>> +       int i, ret;
>>>> +
>>>> +       if (num > QUEUE_MULTI_MAX)
>>>> +               num = QUEUE_MULTI_MAX;
>>>> +
>>>> +       queue = queue_to_qentry(handle);
>>>> +
>>>> +       ret = queue->s.dequeue_multi(queue, buf_hdr, num);
>>>> +
>>>> +       for (i = 0; i < ret; i++)
>>>> +               buf[i] = (odp_buffer_t) buf_hdr[i];
>>>> +
>>>> +       return ret;
>>>> +}
>>>> +
>>>> +
>>>> +odp_buffer_t odp_queue_deq(odp_queue_t handle)
>>>> +{
>>>> +       queue_entry_t *queue;
>>>> +       odp_buffer_hdr_t *buf_hdr;
>>>> +
>>>> +       queue   = queue_to_qentry(handle);
>>>> +       buf_hdr = queue->s.dequeue(queue);
>>>> +
>>>> +       if (buf_hdr)
>>>> +               return (odp_buffer_t) buf_hdr;
>>>> +
>>>> +       return ODP_BUFFER_INVALID;
>>>> +}
>>>> +
>>>> +
>>>> +void queue_lock(queue_entry_t *queue)
>>>> +{
>>>> +       LOCK(&queue->s.lock);
>>>> +}
>>>> +
>>>> +
>>>> +void queue_unlock(queue_entry_t *queue)
>>>> +{
>>>> +       UNLOCK(&queue->s.lock);
>>>> +}
>>>> --
>>>> 1.9.1
>>>>
>>>>
>>>> _______________________________________________
>>>> lng-odp mailing list
>>>> lng-odp@lists.linaro.org
>>>> http://lists.linaro.org/mailman/listinfo/lng-odp
>>>>
>>>
>>>
>>>
>>> --
>>> *Mike Holmes*
>>> Linaro Technical Manager / Lead
>>> LNG - ODP
>>>
>>
>>
>
>
> --
> *Mike Holmes*
> Linaro Technical Manager / Lead
> LNG - ODP
>
diff mbox

Patch

diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile
new file mode 100644
index 0000000..bf8d0b3
--- /dev/null
+++ b/platform/linux-dpdk/Makefile
@@ -0,0 +1,158 @@ 
+## Copyright (c) 2013, Linaro Limited
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are met:
+##
+##    * Redistributions of source code must retain the above copyright notice, this
+##      list of conditions and the following disclaimer.
+##
+##    * Redistributions in binary form must reproduce the above copyright notice, this
+##      list of conditions and the following disclaimer in the documentation and/or
+##      other materials provided with the distribution.
+##
+##    * Neither the name of Linaro Limited nor the names of its contributors may be
+##      used to endorse or promote products derived from this software without specific
+##      prior written permission.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+.DEFAULT_GOAL := libs
+
+ODP_ROOT = ../..
+LIB_DIR  = ./lib
+DOC_DIR  = ./doc
+
+LINUX_GENERIC_DIR = ../linux-generic
+
+RTE_SDK    ?= $(abspath $(ODP_ROOT)/../dpdk)
+RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build)
+RTE_LIB    ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a)
+
+PLAT_CFLAGS  = -include $(RTE_OUTPUT)/include/rte_config.h
+PLAT_CFLAGS += -I$(RTE_OUTPUT)/include
+PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch
+PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env
+PLAT_CFLAGS += -msse4.2
+
+EXTRA_CFLAGS += $(PLAT_CFLAGS)
+EXTRA_CFLAGS += -I./include
+EXTRA_CFLAGS += -I./include/api
+EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include
+EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api
+EXTRA_CFLAGS += -I$(ODP_ROOT)/include
+
+include $(ODP_ROOT)/Makefile.inc
+STATIC_LIB = ./lib/libodp.a
+
+#
+# Object files
+#
+OBJS     =
+OBJS    += $(OBJ_DIR)/odp_barrier.o
+OBJS    += $(OBJ_DIR)/odp_buffer.o
+OBJS    += $(OBJ_DIR)/odp_buffer_pool.o
+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
+OBJS    += $(OBJ_DIR)/odp_schedule.o
+OBJS    += $(OBJ_DIR)/odp_shared_memory.o
+OBJS    += $(OBJ_DIR)/odp_spinlock.o
+OBJS    += $(OBJ_DIR)/odp_system_info.o
+OBJS    += $(OBJ_DIR)/odp_thread.o
+OBJS    += $(OBJ_DIR)/odp_ticketlock.o
+OBJS    += $(OBJ_DIR)/odp_time.o
+OBJS    += $(OBJ_DIR)/odp_timer.o
+OBJS    += $(OBJ_DIR)/odp_ring.o
+OBJS    += $(OBJ_DIR)/odp_rwlock.o
+OBJS    += $(OBJ_DIR)/odp_packet_dpdk.o
+
+DEPS     = $(OBJS:.o=.d)
+
+.PHONY: all
+all: libs docs
+
+-include $(DEPS)
+
+#$(OBJ_DIR):
+#	$(MKDIR) $(OBJ_DIR)
+
+$(LIB_DIR):
+	$(MKDIR) $(LIB_DIR)
+
+$(DOC_DIR):
+	$(MKDIR) $(DOC_DIR)/html
+	$(MKDIR) $(DOC_DIR)/latex
+
+#
+# Compile rules
+#
+vpath %.c source:$(LINUX_GENERIC_DIR)/source
+
+$(OBJ_DIR)/%.o: %.c
+	$(ECHO) "  CC    $<"
+	$(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $<
+
+#
+# Lib rule
+#
+$(OBJ_DIR)/libodp.o: $(OBJS)
+	$(ECHO) "  LD    $@"
+	$(LD) -r -o $@ $(OBJS) $(RTE_LIB)
+
+$(STATIC_LIB): $(OBJ_DIR)/libodp.o
+	$(ECHO) "  AR    $@"
+	$(AR) -cr $@ $(OBJ_DIR)/libodp.o
+
+
+clean:
+	$(RMDIR) $(OBJ_DIR)
+	$(RMDIR) $(LIB_DIR)
+	$(RMDIR) $(DOC_DIR)
+	$(RM) Doxyfile
+
+Doxyfile: Doxyfile.in
+	doxygen -u - < $< > $@
+
+.PHONY: docs
+docs: $(DOC_DIR) Doxyfile ./include/odp*.h
+	doxygen
+
+.PHONY: docs_install
+docs_install: docs
+	$(COPY) doc $(DESTDIR)
+
+.PHONY: pdf
+pdf: docs
+	make --directory doc/latex refman.pdf 1> /dev/null
+
+.PHONY: libs
+libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB)
+
+.PHONY: lib_install
+lib_install: libs
+	install -d $(DESTDIR)/lib
+	install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/
+
+.PHONY: headers_install
+headers_install: libs
+	$(ECHO) Installing headers to $(DESTDIR)/include
+	$(COPY) $(ODP_ROOT)/include $(DESTDIR)
+	$(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/
+	$(COPY) include/api/* $(DESTDIR)/include/
+
+install: lib_install headers_install
diff --git a/platform/linux-dpdk/Makefile.inc b/platform/linux-dpdk/Makefile.inc
new file mode 100644
index 0000000..fe7679b
--- /dev/null
+++ b/platform/linux-dpdk/Makefile.inc
@@ -0,0 +1,7 @@ 
+# Copyright (c) 2013, Linaro Limited
+# All rights reserved.
+#
+# SPDX-License-Identifier:	BSD-3-Clause
+
+STD_LIBS += -ldl
+
diff --git a/platform/linux-dpdk/include/api/odp_buffer.h b/platform/linux-dpdk/include/api/odp_buffer.h
new file mode 100644
index 0000000..286d9e6
--- /dev/null
+++ b/platform/linux-dpdk/include/api/odp_buffer.h
@@ -0,0 +1,101 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP buffer descriptor
+ */
+
+#ifndef ODP_BUFFER_H_
+#define ODP_BUFFER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#include <odp_std_types.h>
+
+
+
+
+
+/**
+ * ODP buffer
+ */
+typedef unsigned long odp_buffer_t;
+
+
+#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */
+
+
+/**
+ * Buffer start address
+ *
+ * @param buf      Buffer handle
+ *
+ * @return Buffer start address
+ */
+void *odp_buffer_addr(odp_buffer_t buf);
+
+/**
+ * Buffer maximum data size
+ *
+ * @param buf      Buffer handle
+ *
+ * @return Buffer maximum data size
+ */
+size_t odp_buffer_size(odp_buffer_t buf);
+
+/**
+ * Buffer type
+ *
+ * @param buf      Buffer handle
+ *
+ * @return Buffer type
+ */
+int odp_buffer_type(odp_buffer_t buf);
+
+#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */
+#define ODP_BUFFER_TYPE_RAW       0  /**< Raw buffer */
+#define ODP_BUFFER_TYPE_PACKET    1  /**< Packet buffer */
+#define ODP_BUFFER_TYPE_TIMER     2  /**< Timer buffer */
+
+/**
+ * Tests if buffer is part of a scatter/gather list
+ *
+ * @param buf      Buffer handle
+ *
+ * @return 1 if belongs to a scatter list, otherwise 0
+ */
+int odp_buffer_is_scatter(odp_buffer_t buf);
+
+/**
+ * Tests if buffer is valid
+ *
+ * @param buf      Buffer handle
+ *
+ * @return 1 if valid, otherwise 0
+ */
+int odp_buffer_is_valid(odp_buffer_t buf);
+
+/**
+ * Print buffer metadata to STDOUT
+ *
+ * @param buf      Buffer handle
+ *
+ */
+void odp_buffer_print(odp_buffer_t buf);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h b/platform/linux-dpdk/include/api/odp_buffer_pool.h
new file mode 100644
index 0000000..4b75cf5
--- /dev/null
+++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h
@@ -0,0 +1,99 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP buffer pool
+ */
+
+#ifndef ODP_BUFFER_POOL_H_
+#define ODP_BUFFER_POOL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#include <odp_std_types.h>
+#include <odp_buffer.h>
+
+/** Maximum queue name lenght in chars */
+#define ODP_BUFFER_POOL_NAME_LEN  32
+
+/** Invalid buffer pool */
+#define ODP_BUFFER_POOL_INVALID  (0xffffffff)
+
+/** ODP buffer pool */
+typedef unsigned long odp_buffer_pool_t;
+
+
+/**
+ * Create a buffer pool
+ *
+ * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)
+ * @param base_addr Pool base address
+ * @param size      Pool size in bytes
+ * @param buf_size  Buffer size in bytes
+ * @param buf_align Minimum buffer alignment
+ * @param buf_type  Buffer type
+ *
+ * @return Buffer pool handle
+ */
+odp_buffer_pool_t odp_buffer_pool_create(const char *name,
+					 void *base_addr, uint64_t size,
+					 size_t buf_size, size_t buf_align,
+					 int buf_type);
+
+
+/**
+ * Find a buffer pool by name
+ *
+ * @param name      Name of the pool
+ *
+ * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
+ */
+odp_buffer_pool_t odp_buffer_pool_lookup(const char *name);
+
+
+/**
+ * Print buffer pool info
+ *
+ * @param pool      Pool handle
+ *
+ */
+void odp_buffer_pool_print(odp_buffer_pool_t pool);
+
+
+
+/**
+ * Buffer alloc
+ *
+ * @param pool      Pool handle
+ *
+ * @return Buffer handle or ODP_BUFFER_INVALID
+ */
+odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool);
+
+
+/**
+ * Buffer free
+ *
+ * @param buf       Buffer handle
+ *
+ */
+void odp_buffer_free(odp_buffer_t buf);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-dpdk/include/api/odp_packet.h b/platform/linux-dpdk/include/api/odp_packet.h
new file mode 100644
index 0000000..bdb3417
--- /dev/null
+++ b/platform/linux-dpdk/include/api/odp_packet.h
@@ -0,0 +1,228 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP packet descriptor
+ */
+
+#ifndef ODP_PACKET_H_
+#define ODP_PACKET_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_buffer.h>
+
+
+/**
+ * ODP packet descriptor
+ */
+typedef unsigned long odp_packet_t;
+
+
+/** Invalid packet */
+#define ODP_PACKET_INVALID ODP_BUFFER_INVALID
+
+/** Invalid offset */
+#define ODP_PACKET_OFFSET_INVALID ((size_t)-1)
+
+
+/**
+ * Initialize the packet
+ *
+ * Needs to be called if the user allocates a packet buffer, i.e. the packet
+ * has not been received from I/O through ODP.
+ *
+ * @param pkt  Packet handle
+ */
+void odp_packet_init(odp_packet_t pkt);
+
+/**
+ * Convert from packet handle to buffer handle
+ *
+ * @param buf  Buffer handle
+ *
+ * @return Packet handle
+ */
+odp_packet_t odp_packet_from_buffer(odp_buffer_t buf);
+
+/**
+ * Convert from buffer handle to packet handle
+ *
+ * @param pkt  Packet handle
+ *
+ * @return Buffer handle
+ */
+odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt);
+
+/**
+ * Set the packet length
+ *
+ * @param pkt  Packet handle
+ * @param len  Length of packet in bytes
+ */
+void odp_packet_set_len(odp_packet_t pkt, size_t len);
+
+/**
+ * Get the packet length
+ *
+ * @param pkt  Packet handle
+ *
+ * @return   Packet length in bytes
+ */
+size_t odp_packet_get_len(odp_packet_t pkt);
+
+/**
+ * Get address to the start of the packet buffer
+ *
+ * The address of the packet buffer is not necessarily the same as the start
+ * address of the received frame, e.g. an eth frame may be offset by 2 or 6
+ * bytes to ensure 32 or 64-bit alignment of the IP header.
+ * Use odp_packet_l2(pkt) to get the start address of a received valid frame
+ * or odp_packet_start(pkt) to get the start address even if no valid L2 header
+ * could be found.
+ *
+ * @param pkt  Packet handle
+ *
+ * @return  Pointer to the start of the packet buffer
+ *
+ * @see odp_packet_l2(), odp_packet_start()
+ */
+uint8_t *odp_packet_buf_addr(odp_packet_t pkt);
+
+/**
+ * Get pointer to the start of the received frame
+ *
+ * The address of the packet buffer is not necessarily the same as the start
+ * address of the received frame, e.g. an eth frame may be offset by 2 or 6
+ * bytes to ensure 32 or 64-bit alignment of the IP header.
+ * Use odp_packet_l2(pkt) to get the start address of a received valid eth frame
+ *
+ * odp_packet_start() will always return a pointer to the start of the frame,
+ * even if the frame is unrecognized and no valid L2 header could be found.
+ *
+ * @param pkt  Packet handle
+ *
+ * @return  Pointer to the start of the received frame
+ *
+ * @see odp_packet_l2(), odp_packet_buf_addr()
+ */
+uint8_t *odp_packet_start(odp_packet_t pkt);
+
+/**
+ * Get pointer to the start of the L2 frame
+ *
+ * The L2 frame header address is not necessarily the same as the address of the
+ * packet buffer, see odp_packet_buf_addr()
+ *
+ * @param pkt  Packet handle
+ *
+ * @return  Pointer to L2 header or NULL if not found
+ *
+ * @see odp_packet_buf_addr(), odp_packet_start()
+ */
+uint8_t *odp_packet_l2(odp_packet_t pkt);
+
+/**
+ * Return the byte offset from the packet buffer to the L2 frame
+ *
+ * @param pkt  Packet handle
+ *
+ * @return  L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found
+ */
+size_t odp_packet_l2_offset(odp_packet_t pkt);
+
+/**
+ * Set the byte offset to the L2 frame
+ *
+ * @param pkt     Packet handle
+ * @param offset  L2 byte offset
+ */
+void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset);
+
+
+/**
+ * Get pointer to the start of the L3 packet
+ *
+ * @param pkt  Packet handle
+ *
+ * @return  Pointer to L3 packet or NULL if not found
+ *
+ */
+uint8_t *odp_packet_l3(odp_packet_t pkt);
+
+/**
+ * Return the byte offset from the packet buffer to the L3 packet
+ *
+ * @param pkt  Packet handle
+ *
+ * @return  L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found
+ */
+size_t odp_packet_l3_offset(odp_packet_t pkt);
+
+/**
+ * Set the byte offset to the L3 packet
+ *
+ * @param pkt     Packet handle
+ * @param offset  L3 byte offset
+ */
+void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset);
+
+
+/**
+ * Get pointer to the start of the L4 packet
+ *
+ * @param pkt  Packet handle
+ *
+ * @return  Pointer to L4 packet or NULL if not found
+ *
+ */
+uint8_t *odp_packet_l4(odp_packet_t pkt);
+
+/**
+ * Return the byte offset from the packet buffer to the L4 packet
+ *
+ * @param pkt  Packet handle
+ *
+ * @return  L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found
+ */
+size_t odp_packet_l4_offset(odp_packet_t pkt);
+
+/**
+ * Set the byte offset to the L4 packet
+ *
+ * @param pkt     Packet handle
+ * @param offset  L4 byte offset
+ */
+void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset);
+
+/**
+ * Print (debug) information about the packet
+ *
+ * @param pkt  Packet handle
+ */
+void odp_packet_print(odp_packet_t pkt);
+
+/**
+ * Copy contents and metadata from pkt_src to pkt_dst
+ * Useful when creating copies of packets
+ *
+ * @param pkt_dst Destination packet
+ * @param pkt_src Source packet
+ *
+ * @return 0 if successful
+ */
+int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h b/platform/linux-dpdk/include/api/odp_pktio_types.h
new file mode 100644
index 0000000..b23e6da
--- /dev/null
+++ b/platform/linux-dpdk/include/api/odp_pktio_types.h
@@ -0,0 +1,45 @@ 
+
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_PKTIO_TYPES_H
+#define ODP_PKTIO_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* We should ensure that future enum values will never overlap, otherwise
+ * applications that want netmap suport might get in trouble if the odp lib
+ * was not built with netmap support and there are more types define below
+ */
+
+typedef enum {
+	ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1,
+	ODP_PKTIO_TYPE_SOCKET_MMSG,
+	ODP_PKTIO_TYPE_SOCKET_MMAP,
+	ODP_PKTIO_TYPE_NETMAP,
+	ODP_PKTIO_TYPE_DPDK,
+} odp_pktio_type_t;
+
+#include <odp_pktio_socket.h>
+#ifdef ODP_HAVE_NETMAP
+#include <odp_pktio_netmap.h>
+#endif
+
+typedef union odp_pktio_params_t {
+	odp_pktio_type_t type;
+	socket_params_t sock_params;
+#ifdef ODP_HAVE_NETMAP
+	netmap_params_t nm_params;
+#endif
+} odp_pktio_params_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h b/platform/linux-dpdk/include/odp_buffer_internal.h
new file mode 100644
index 0000000..a47107c
--- /dev/null
+++ b/platform/linux-dpdk/include/odp_buffer_internal.h
@@ -0,0 +1,79 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP buffer descriptor - implementation internal
+ */
+
+#ifndef ODP_BUFFER_INTERNAL_H_
+#define ODP_BUFFER_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_std_types.h>
+#include <odp_atomic.h>
+#include <odp_buffer_pool.h>
+#include <odp_buffer.h>
+#include <odp_debug.h>
+#include <odp_align.h>
+#include <rte_mbuf.h>
+
+/* TODO: move these to correct files */
+
+typedef uint64_t odp_phys_addr_t;
+
+#define ODP_BUFFER_MAX_INDEX     (ODP_BUFFER_MAX_BUFFERS - 2)
+#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1)
+
+#define ODP_BUFS_PER_CHUNK       16
+#define ODP_BUFS_PER_SCATTER      4
+
+#define ODP_BUFFER_TYPE_CHUNK    0xffff
+
+
+#define ODP_BUFFER_POOL_BITS   4
+#define ODP_BUFFER_INDEX_BITS  (32 - ODP_BUFFER_POOL_BITS)
+#define ODP_BUFFER_MAX_POOLS   (1 << ODP_BUFFER_POOL_BITS)
+#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS)
+
+typedef union odp_buffer_bits_t {
+	uint32_t     u32;
+	odp_buffer_t handle;
+
+	struct {
+		uint32_t pool:ODP_BUFFER_POOL_BITS;
+		uint32_t index:ODP_BUFFER_INDEX_BITS;
+	};
+} odp_buffer_bits_t;
+
+
+/* forward declaration */
+struct odp_buffer_hdr_t;
+
+
+typedef struct rte_mbuf odp_buffer_hdr_t;
+
+
+int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
+
+
+
diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
new file mode 100644
index 0000000..1a36655
--- /dev/null
+++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h
@@ -0,0 +1,90 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP buffer pool - internal header
+ */
+
+#ifndef ODP_BUFFER_POOL_INTERNAL_H_
+#define ODP_BUFFER_POOL_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_std_types.h>
+#include <odp_buffer_pool.h>
+#include <odp_buffer_internal.h>
+#include <odp_align.h>
+#include <odp_hints.h>
+#include <odp_config.h>
+#include <odp_debug.h>
+
+/* for DPDK */
+#include <rte_mempool.h>
+
+/* Use ticketlock instead of spinlock */
+#define POOL_USE_TICKETLOCK
+
+/* Extra error checks */
+/* #define POOL_ERROR_CHECK */
+
+
+#ifdef POOL_USE_TICKETLOCK
+#include <odp_ticketlock.h>
+#else
+#include <odp_spinlock.h>
+#endif
+
+
+struct pool_entry_s {
+#ifdef POOL_USE_TICKETLOCK
+	odp_ticketlock_t        lock ODP_ALIGNED_CACHE;
+#else
+	odp_spinlock_t          lock ODP_ALIGNED_CACHE;
+#endif
+
+	uint64_t                free_bufs;
+	char                    name[ODP_BUFFER_POOL_NAME_LEN];
+
+
+	odp_buffer_pool_t       pool ODP_ALIGNED_CACHE;
+	uintptr_t               buf_base;
+	size_t                  buf_size;
+	size_t                  buf_offset;
+	uint64_t                num_bufs;
+	void                   *pool_base_addr;
+	uint64_t                pool_size;
+	size_t                  payload_size;
+	size_t                  payload_align;
+	int                     buf_type;
+	size_t                  hdr_size;
+};
+
+
+extern void *pool_entry_ptr[];
+
+
+static inline void *get_pool_entry(odp_buffer_pool_t pool_id)
+{
+	return pool_entry_ptr[pool_id];
+}
+
+
+static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf)
+{
+	return (odp_buffer_hdr_t *)buf;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h b/platform/linux-dpdk/include/odp_packet_dpdk.h
new file mode 100644
index 0000000..0b3db08
--- /dev/null
+++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
@@ -0,0 +1,88 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_PACKET_DPDK_H
+#define ODP_PACKET_DPDK_H
+
+#include <stdint.h>
+#include <net/if.h>
+
+#include <helper/odp_eth.h>
+#include <helper/odp_packet_helper.h>
+#include <odp_align.h>
+#include <odp_debug.h>
+#include <odp_packet.h>
+#include <odp_packet_internal.h>
+#include <odp_buffer_pool.h>
+#include <odp_buffer_pool_internal.h>
+#include <odp_buffer_internal.h>
+#include <odp_std_types.h>
+
+#include <rte_config.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_prefetch.h>
+#include <rte_cycles.h>
+#include <rte_errno.h>
+#include <rte_debug.h>
+#include <rte_log.h>
+#include <rte_byteorder.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_hash.h>
+#include <rte_jhash.h>
+#include <rte_hash_crc.h>
+
+
+#define ODP_DPDK_MODE_HW	0
+#define ODP_DPDK_MODE_SW	1
+
+#define DPDK_BLOCKING_IO
+
+/** Packet socket using dpdk mmaped rings for both Rx and Tx */
+typedef struct {
+	odp_buffer_pool_t pool;
+
+	/********************************/
+	char ifname[32];
+	uint8_t portid;
+	uint16_t queueid;
+} pkt_dpdk_t;
+
+/**
+ * Configure an interface to work in dpdk mode
+ */
+int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
+		   odp_buffer_pool_t pool);
+
+/**
+ * Switch interface from dpdk mode to normal mode
+ */
+int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk);
+
+/**
+ * Receive packets using dpdk
+ */
+int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
+		  unsigned len);
+
+/**
+ * Send packets using dpdk
+ */
+int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
+		  unsigned len);
+
+int odp_init_dpdk(void);
+#endif
+
diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h
new file mode 100644
index 0000000..d9057a2
--- /dev/null
+++ b/platform/linux-dpdk/include/odp_packet_internal.h
@@ -0,0 +1,140 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP packet descriptor - implementation internal
+ */
+
+#ifndef ODP_PACKET_INTERNAL_H_
+#define ODP_PACKET_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_align.h>
+#include <odp_debug.h>
+#include <odp_buffer_internal.h>
+#include <odp_buffer_pool_internal.h>
+#include <odp_packet.h>
+#include <odp_packet_io.h>
+
+/**
+ * Packet input & protocol flags
+ */
+typedef union {
+	/* All input flags */
+	uint32_t all;
+
+	struct {
+		/* 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:1;     /**< 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;
+
+	struct {
+		/* 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;
+
+ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t), ERROR_FLAGS_SIZE_ERROR);
+
+/**
+ * Packet output flags
+ */
+typedef union {
+	/* All output flags */
+	uint32_t all;
+
+	struct {
+		/* 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 {
+	/* common buffer header */
+	odp_buffer_hdr_t buf_hdr;
+
+	input_flags_t  input_flags;
+	error_flags_t  error_flags;
+	output_flags_t output_flags;
+
+	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;
+
+/**
+ * Return the packet header
+ */
+static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt)
+{
+	return (odp_packet_hdr_t *)pkt;
+}
+
+/**
+ * Parse packet and set internal metadata
+ */
+void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h b/platform/linux-dpdk/include/odp_packet_io_internal.h
new file mode 100644
index 0000000..5948063
--- /dev/null
+++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
@@ -0,0 +1,52 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP packet IO - implementation internal
+ */
+
+#ifndef ODP_PACKET_IO_INTERNAL_H_
+#define ODP_PACKET_IO_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp_spinlock.h>
+#include <odp_packet_socket.h>
+#ifdef ODP_HAVE_NETMAP
+#include <odp_packet_netmap.h>
+#endif
+#include <odp_packet_dpdk.h>
+
+struct pktio_entry {
+	odp_spinlock_t lock;		/**< entry spinlock */
+	int taken;			/**< is entry taken(1) or free(0) */
+	odp_queue_t inq_default;	/**< default input queue, if set */
+	odp_queue_t outq_default;	/**< default out queue */
+	odp_pktio_params_t params;	/**< pktio parameters */
+	pkt_sock_t pkt_sock;		/**< using socket API for IO */
+	pkt_sock_mmap_t pkt_sock_mmap;	/**< using socket mmap API for IO */
+#ifdef ODP_HAVE_NETMAP
+	pkt_netmap_t pkt_nm;		/**< using netmap API for IO */
+#endif
+	pkt_dpdk_t pkt_dpdk;		/**< using DPDK API for IO */
+};
+
+typedef union {
+	struct pktio_entry s;
+	uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct pktio_entry))];
+} pktio_entry_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/platform/linux-dpdk/source/odp_buffer.c b/platform/linux-dpdk/source/odp_buffer.c
new file mode 100644
index 0000000..bfb5ff6
--- /dev/null
+++ b/platform/linux-dpdk/source/odp_buffer.c
@@ -0,0 +1,102 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_buffer.h>
+#include <odp_buffer_internal.h>
+#include <odp_buffer_pool_internal.h>
+
+#include <string.h>
+#include <stdio.h>
+
+
+void *odp_buffer_addr(odp_buffer_t buf)
+{
+	odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
+
+	return hdr->buf_addr;
+}
+
+
+size_t odp_buffer_size(odp_buffer_t buf)
+{
+	odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
+
+	return hdr->buf_len;
+}
+
+
+int odp_buffer_type(odp_buffer_t buf)
+{
+	odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
+
+	return hdr->type;
+}
+
+
+int odp_buffer_is_scatter(odp_buffer_t buf)
+{
+	odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf);
+
+	if (hdr->refcnt == 0)
+		return 0;
+	else
+		return 1;
+}
+
+
+int odp_buffer_is_valid(odp_buffer_t buf)
+{
+	odp_buffer_bits_t handle;
+
+	handle.u32 = buf;
+
+	return (handle.index != ODP_BUFFER_INVALID_INDEX);
+}
+
+
+int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf)
+{
+	odp_buffer_hdr_t *hdr;
+	int len = 0;
+
+	if (!odp_buffer_is_valid(buf)) {
+		printf("Buffer is not valid.\n");
+		return len;
+	}
+
+	hdr = odp_buf_to_hdr(buf);
+
+	len += snprintf(&str[len], n-len,
+			"Buffer\n");
+	len += snprintf(&str[len], n-len,
+			"  pool         %"PRIu64"\n", (int64_t) hdr->pool);
+	len += snprintf(&str[len], n-len,
+			"  phy_addr     %"PRIu64"\n", hdr->buf_physaddr);
+	len += snprintf(&str[len], n-len,
+			"  addr         %p\n",        hdr->buf_addr);
+	len += snprintf(&str[len], n-len,
+			"  size         %u\n",        hdr->buf_len);
+	len += snprintf(&str[len], n-len,
+			"  ref_count    %i\n",        hdr->refcnt);
+	len += snprintf(&str[len], n-len,
+			"  type         %i\n",        hdr->type);
+
+	return len;
+}
+
+
+void odp_buffer_print(odp_buffer_t buf)
+{
+	int max_len = 512;
+	char str[max_len];
+	int len;
+
+	len = odp_buffer_snprint(str, max_len-1, buf);
+	str[len] = 0;
+
+	printf("\n%s\n", str);
+}
+
diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c b/platform/linux-dpdk/source/odp_buffer_pool.c
new file mode 100644
index 0000000..de90275
--- /dev/null
+++ b/platform/linux-dpdk/source/odp_buffer_pool.c
@@ -0,0 +1,156 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_std_types.h>
+#include <odp_buffer_pool.h>
+#include <odp_buffer_pool_internal.h>
+#include <odp_buffer_internal.h>
+#include <odp_packet_internal.h>
+#include <odp_shared_memory.h>
+#include <odp_align.h>
+#include <odp_internal.h>
+#include <odp_config.h>
+#include <odp_hints.h>
+#include <odp_debug.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+/* for DPDK */
+#include <odp_packet_dpdk.h>
+
+#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
+#define NB_MBUF   8192
+
+#ifdef POOL_USE_TICKETLOCK
+#include <odp_ticketlock.h>
+#define LOCK(a)      odp_ticketlock_lock(a)
+#define UNLOCK(a)    odp_ticketlock_unlock(a)
+#define LOCK_INIT(a) odp_ticketlock_init(a)
+#else
+#include <odp_spinlock.h>
+#define LOCK(a)      odp_spinlock_lock(a)
+#define UNLOCK(a)    odp_spinlock_unlock(a)
+#define LOCK_INIT(a) odp_spinlock_init(a)
+#endif
+
+
+#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
+#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS
+#endif
+
+#define NULL_INDEX ((uint32_t)-1)
+
+
+typedef union pool_entry_u {
+	struct pool_entry_s s;
+
+	uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct pool_entry_s))];
+
+} pool_entry_t;
+
+
+typedef struct pool_table_t {
+	pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS];
+
+} pool_table_t;
+
+
+/* The pool table */
+static pool_table_t *pool_tbl;
+
+/* Pool entry pointers (for inlining) */
+void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS];
+
+
+int odp_buffer_pool_init_global(void)
+{
+	odp_buffer_pool_t i;
+
+	pool_tbl = odp_shm_reserve("odp_buffer_pools",
+				   sizeof(pool_table_t),
+				   sizeof(pool_entry_t));
+
+	if (pool_tbl == NULL)
+		return -1;
+
+	memset(pool_tbl, 0, sizeof(pool_table_t));
+
+
+	for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) {
+		/* init locks */
+		pool_entry_t *pool = &pool_tbl->pool[i];
+		LOCK_INIT(&pool->s.lock);
+		pool->s.pool = i;
+
+		pool_entry_ptr[i] = pool;
+	}
+
+	ODP_DBG("\nBuffer pool init global\n");
+	ODP_DBG("  pool_entry_s size     %zu\n", sizeof(struct pool_entry_s));
+	ODP_DBG("  pool_entry_t size     %zu\n", sizeof(pool_entry_t));
+	ODP_DBG("  odp_buffer_hdr_t size %zu\n", sizeof(odp_buffer_hdr_t));
+	ODP_DBG("\n");
+
+	return 0;
+}
+
+
+odp_buffer_pool_t odp_buffer_pool_create(const char *name,
+					 void *base_addr, uint64_t size,
+					 size_t buf_size, size_t buf_align,
+					 int buf_type)
+{
+	struct rte_mempool *pktmbuf_pool = NULL;
+	ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n", name,
+		(uint64_t) base_addr, (unsigned) size,
+		(unsigned) buf_size, (unsigned) buf_align,
+		buf_type);
+
+	pktmbuf_pool =
+		rte_mempool_create(name, NB_MBUF,
+				   MBUF_SIZE, 32,
+				   sizeof(struct rte_pktmbuf_pool_private),
+				   rte_pktmbuf_pool_init, NULL,
+				   rte_pktmbuf_init, NULL,
+				   rte_socket_id(), 0);
+	if (pktmbuf_pool == NULL) {
+		ODP_ERR("Cannot init DPDK mbuf pool\n");
+		return -1;
+	}
+
+	return (odp_buffer_pool_t) pktmbuf_pool;
+}
+
+
+odp_buffer_pool_t odp_buffer_pool_lookup(const char *name)
+{
+	struct rte_mempool *mp = NULL;
+
+	mp = rte_mempool_lookup(name);
+	if (mp == NULL)
+		return ODP_BUFFER_POOL_INVALID;
+
+	return (odp_buffer_pool_t)mp;
+}
+
+
+odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id)
+{
+	return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool *)pool_id);
+}
+
+
+void odp_buffer_free(odp_buffer_t buf)
+{
+	rte_pktmbuf_free((struct rte_mbuf *)buf);
+}
+
+
+void odp_buffer_pool_print(odp_buffer_pool_t pool_id)
+{
+	rte_mempool_dump((const struct rte_mempool *)pool_id);
+}
diff --git a/platform/linux-dpdk/source/odp_init.c b/platform/linux-dpdk/source/odp_init.c
new file mode 100644
index 0000000..ecc2066
--- /dev/null
+++ b/platform/linux-dpdk/source/odp_init.c
@@ -0,0 +1,113 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_init.h>
+#include <odp_internal.h>
+#include <odp_debug.h>
+#include <odp_packet_dpdk.h>
+
+int odp_init_dpdk(void)
+{
+	int test_argc = 5;
+	char *test_argv[6];
+	int core_count, i, num_cores = 0;
+	char core_mask[8];
+
+	core_count  = odp_sys_core_count();
+	for (i = 0; i < core_count; i++)
+		num_cores += (0x1 << i);
+	sprintf(core_mask, "%x", num_cores);
+
+	test_argv[0] = malloc(sizeof("odp_dpdk"));
+	strcpy(test_argv[0], "odp_dpdk");
+	test_argv[1] = malloc(sizeof("-c"));
+	strcpy(test_argv[1], "-c");
+	test_argv[2] = malloc(sizeof(core_mask));
+	strcpy(test_argv[2], core_mask);
+	test_argv[3] = malloc(sizeof("-n"));
+	strcpy(test_argv[3], "-n");
+	test_argv[4] = malloc(sizeof("3"));
+	strcpy(test_argv[4], "3");
+
+	if (rte_eal_init(test_argc, (char **)test_argv) < 0) {
+		ODP_ERR("Cannot init the Intel DPDK EAL!");
+		return -1;
+	}
+
+	if (rte_pmd_init_all() < 0) {
+		ODP_ERR("Cannot init pmd\n");
+		return -1;
+	}
+
+	if (rte_eal_pci_probe() < 0) {
+		ODP_ERR("Cannot probe PCI\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int odp_init_global(void)
+{
+	odp_thread_init_global();
+
+	odp_system_info_init();
+
+	if (odp_init_dpdk()) {
+		ODP_ERR("ODP dpdk init failed.\n");
+		return -1;
+	}
+
+	if (odp_shm_init_global()) {
+		ODP_ERR("ODP shm init failed.\n");
+		return -1;
+	}
+
+	if (odp_buffer_pool_init_global()) {
+		ODP_ERR("ODP buffer pool init failed.\n");
+		return -1;
+	}
+
+	if (odp_queue_init_global()) {
+		ODP_ERR("ODP queue init failed.\n");
+		return -1;
+	}
+
+	if (odp_schedule_init_global()) {
+		ODP_ERR("ODP schedule init failed.\n");
+		return -1;
+	}
+
+	if (odp_pktio_init_global()) {
+		ODP_ERR("ODP packet io init failed.\n");
+		return -1;
+	}
+
+	if (odp_timer_init_global()) {
+		ODP_ERR("ODP timer init failed.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int odp_init_local(int thr_id)
+{
+	odp_thread_init_local(thr_id);
+
+	if (odp_pktio_init_local()) {
+		ODP_ERR("ODP packet io local init failed.\n");
+		return -1;
+	}
+
+	if (odp_schedule_init_local()) {
+		ODP_ERR("ODP schedule local init failed.\n");
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/platform/linux-dpdk/source/odp_packet.c b/platform/linux-dpdk/source/odp_packet.c
new file mode 100644
index 0000000..c34e626
--- /dev/null
+++ b/platform/linux-dpdk/source/odp_packet.c
@@ -0,0 +1,374 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_packet.h>
+#include <odp_packet_internal.h>
+#include <odp_hints.h>
+#include <odp_byteorder.h>
+
+#include <helper/odp_eth.h>
+#include <helper/odp_ip.h>
+
+#include <string.h>
+#include <stdio.h>
+
+static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, odp_ipv4hdr_t *ipv4,
+				size_t *offset_out);
+static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, odp_ipv6hdr_t *ipv6,
+				size_t *offset_out);
+
+void odp_packet_init(odp_packet_t pkt)
+{
+	odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
+	const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr);
+	uint8_t *start;
+	size_t len;
+
+	start = (uint8_t *)pkt_hdr + start_offset;
+	len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
+	memset(start, 0, len);
+
+	pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
+	pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
+	pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID;
+}
+
+odp_packet_t odp_packet_from_buffer(odp_buffer_t buf)
+{
+	return (odp_packet_t)buf;
+}
+
+odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt)
+{
+	return (odp_buffer_t)pkt;
+}
+
+void odp_packet_set_len(odp_packet_t pkt, size_t len)
+{
+	/* for rte_pktmbuf */
+	odp_buffer_hdr_t *buf_hdr = odp_buf_to_hdr(odp_buffer_from_packet(pkt));
+	buf_hdr->pkt.data_len = len;
+
+	odp_packet_hdr(pkt)->frame_len = len;
+}
+
+size_t odp_packet_get_len(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->frame_len;
+}
+
+uint8_t *odp_packet_buf_addr(odp_packet_t pkt)
+{
+	return odp_buffer_addr(odp_buffer_from_packet(pkt));
+}
+
+uint8_t *odp_packet_start(odp_packet_t pkt)
+{
+	return odp_packet_buf_addr(pkt) + odp_packet_hdr(pkt)->frame_offset;
+}
+
+
+uint8_t *odp_packet_l2(odp_packet_t pkt)
+{
+	const size_t offset = odp_packet_l2_offset(pkt);
+
+	if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
+		return NULL;
+
+	return odp_packet_buf_addr(pkt) + offset;
+}
+
+size_t odp_packet_l2_offset(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->l2_offset;
+}
+
+void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset)
+{
+	odp_packet_hdr(pkt)->l2_offset = offset;
+}
+
+uint8_t *odp_packet_l3(odp_packet_t pkt)
+{
+	const size_t offset = odp_packet_l3_offset(pkt);
+
+	if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
+		return NULL;
+
+	return odp_packet_buf_addr(pkt) + offset;
+}
+
+size_t odp_packet_l3_offset(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->l3_offset;
+}
+
+void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset)
+{
+	odp_packet_hdr(pkt)->l3_offset = offset;
+}
+
+uint8_t *odp_packet_l4(odp_packet_t pkt)
+{
+	const size_t offset = odp_packet_l4_offset(pkt);
+
+	if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
+		return NULL;
+
+	return odp_packet_buf_addr(pkt) + offset;
+}
+
+size_t odp_packet_l4_offset(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->l4_offset;
+}
+
+void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset)
+{
+	odp_packet_hdr(pkt)->l4_offset = offset;
+}
+
+/**
+ * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP
+ *
+ * Internal function: caller is resposible for passing only valid packet handles
+ * , lengths and offsets (usually done&called in packet input).
+ *
+ * @param pkt        Packet handle
+ * @param len        Packet length in bytes
+ * @param frame_offset  Byte offset to L2 header
+ */
+void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset)
+{
+	odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt);
+	odp_ethhdr_t *eth;
+	odp_vlanhdr_t *vlan;
+	odp_ipv4hdr_t *ipv4;
+	odp_ipv6hdr_t *ipv6;
+	uint16_t ethtype;
+	size_t offset = 0;
+	uint8_t ip_proto = 0;
+
+	pkt_hdr->input_flags.eth = 1;
+	pkt_hdr->frame_offset = frame_offset;
+	pkt_hdr->frame_len = len;
+
+	if (odp_unlikely(len < ODP_ETH_LEN_MIN)) {
+		pkt_hdr->error_flags.frame_len = 1;
+		return;
+	} else if (len > ODP_ETH_LEN_MAX) {
+		pkt_hdr->input_flags.jumbo = 1;
+	}
+
+	/* Assume valid L2 header, no CRC/FCS check in SW */
+	pkt_hdr->input_flags.l2 = 1;
+	pkt_hdr->l2_offset = frame_offset;
+
+	eth = (odp_ethhdr_t *)odp_packet_start(pkt);
+	ethtype = odp_be_to_cpu_16(eth->type);
+	vlan = (odp_vlanhdr_t *)&eth->type;
+
+	if (ethtype == ODP_ETHTYPE_VLAN_OUTER) {
+		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->input_flags.vlan = 1;
+		ethtype = odp_be_to_cpu_16(vlan->tpid);
+		offset += sizeof(odp_vlanhdr_t);
+	}
+
+	/* Set l3_offset+flag only for known ethtypes */
+	switch (ethtype) {
+	case ODP_ETHTYPE_IPV4:
+		pkt_hdr->input_flags.ipv4 = 1;
+		pkt_hdr->input_flags.l3 = 1;
+		pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + offset;
+		ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
+		ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset);
+		break;
+	case ODP_ETHTYPE_IPV6:
+		pkt_hdr->input_flags.ipv6 = 1;
+		pkt_hdr->input_flags.l3 = 1;
+		pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + offset;
+		ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt);
+		ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset);
+		break;
+	case ODP_ETHTYPE_ARP:
+		pkt_hdr->input_flags.arp = 1;
+		/* fall through */
+	default:
+		ip_proto = 0;
+		break;
+	}
+
+	switch (ip_proto) {
+	case ODP_IPPROTO_UDP:
+		pkt_hdr->input_flags.udp = 1;
+		pkt_hdr->input_flags.l4 = 1;
+		pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
+		break;
+	case ODP_IPPROTO_TCP:
+		pkt_hdr->input_flags.tcp = 1;
+		pkt_hdr->input_flags.l4 = 1;
+		pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
+		break;
+	case ODP_IPPROTO_SCTP:
+		pkt_hdr->input_flags.sctp = 1;
+		pkt_hdr->input_flags.l4 = 1;
+		pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
+		break;
+	case ODP_IPPROTO_ICMP:
+		pkt_hdr->input_flags.icmp = 1;
+		pkt_hdr->input_flags.l4 = 1;
+		pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset;
+		break;
+	default:
+		/* 0 or unhandled IP protocols, don't set L4 flag+offset */
+		if (pkt_hdr->input_flags.ipv6) {
+			/* IPv6 next_hdr is not L4, mark as IP-option instead */
+			pkt_hdr->input_flags.ipopt = 1;
+		}
+		break;
+	}
+}
+
+static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, odp_ipv4hdr_t *ipv4,
+				size_t *offset_out)
+{
+	uint8_t ihl;
+	uint16_t frag_offset;
+
+	ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl);
+	if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) {
+		pkt_hdr->error_flags.ip_err = 1;
+		return 0;
+	}
+
+	if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) {
+		pkt_hdr->input_flags.ipopt = 1;
+		return 0;
+	}
+
+	/* A packet is a fragment if:
+	*  "more fragments" flag is set (all fragments except the last)
+	*     OR
+	*  "fragment offset" field is nonzero (all fragments except the first)
+	*/
+	frag_offset = odp_be_to_cpu_16(ipv4->frag_offset);
+	if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) {
+		pkt_hdr->input_flags.ipfrag = 1;
+		return 0;
+	}
+
+	if (ipv4->proto == ODP_IPPROTO_ESP ||
+	    ipv4->proto == ODP_IPPROTO_AH) {
+		pkt_hdr->input_flags.ipsec = 1;
+		return 0;
+	}
+
+	/* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after return */
+
+	*offset_out = sizeof(uint32_t) * ihl;
+	return ipv4->proto;
+}
+
+static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, odp_ipv6hdr_t *ipv6,
+				size_t *offset_out)
+{
+	if (ipv6->next_hdr == ODP_IPPROTO_ESP ||
+	    ipv6->next_hdr == ODP_IPPROTO_AH) {
+		pkt_hdr->input_flags.ipopt = 1;
+		pkt_hdr->input_flags.ipsec = 1;
+		return 0;
+	}
+
+	if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) {
+		pkt_hdr->input_flags.ipopt = 1;
+		pkt_hdr->input_flags.ipfrag = 1;
+		return 0;
+	}
+
+	/* Don't step through more extensions */
+	*offset_out = ODP_IPV6HDR_LEN;
+	return ipv6->next_hdr;
+}
+
+void odp_packet_print(odp_packet_t pkt)
+{
+	int max_len = 512;
+	char str[max_len];
+	int len = 0;
+	int n = max_len-1;
+	odp_packet_hdr_t *hdr = odp_packet_hdr(pkt);
+
+	len += snprintf(&str[len], n-len, "Packet ");
+	len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt);
+	len += snprintf(&str[len], n-len,
+			"  input_flags  0x%x\n", hdr->input_flags.all);
+	len += snprintf(&str[len], n-len,
+			"  error_flags  0x%x\n", hdr->error_flags.all);
+	len += snprintf(&str[len], n-len,
+			"  output_flags 0x%x\n", hdr->output_flags.all);
+	len += snprintf(&str[len], n-len,
+			"  frame_offset %u\n", hdr->frame_offset);
+	len += snprintf(&str[len], n-len,
+			"  l2_offset    %u\n", hdr->l2_offset);
+	len += snprintf(&str[len], n-len,
+			"  l3_offset    %u\n", hdr->l3_offset);
+	len += snprintf(&str[len], n-len,
+			"  l4_offset    %u\n", hdr->l4_offset);
+	len += snprintf(&str[len], n-len,
+			"  frame_len    %u\n", hdr->frame_len);
+	len += snprintf(&str[len], n-len,
+			"  input        %u\n", hdr->input);
+	str[len] = '\0';
+
+	printf("\n%s\n", str);
+}
+
+int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src)
+{
+	odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst);
+	odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src);
+	const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr);
+	uint8_t *start_src;
+	uint8_t *start_dst;
+	size_t len;
+
+	if (pkt_dst == ODP_PACKET_INVALID || pkt_src == ODP_PACKET_INVALID)
+		return -1;
+
+	/* if (pkt_hdr_dst->buf_hdr.size < */
+	/*	pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */
+	if (pkt_hdr_dst->buf_hdr.buf_len <
+		pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset)
+		return -1;
+
+	/* Copy packet header */
+	start_dst = (uint8_t *)pkt_hdr_dst + start_offset;
+	start_src = (uint8_t *)pkt_hdr_src + start_offset;
+	len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset;
+	memcpy(start_dst, start_src, len);
+
+	/* Copy frame payload */
+	start_dst = (uint8_t *)odp_packet_start(pkt_dst);
+	start_src = (uint8_t *)odp_packet_start(pkt_src);
+	len = pkt_hdr_src->frame_len;
+	memcpy(start_dst, start_src, len);
+
+	/* Copy useful things from the buffer header */
+	/* pkt_hdr_dst->buf_hdr.cur_offset = pkt_hdr_src->buf_hdr.cur_offset; */
+
+	/* Create a copy of the scatter list */
+	/* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */
+	/*			odp_buffer_from_packet(pkt_src)); */
+
+	return 0;
+}
diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c b/platform/linux-dpdk/source/odp_packet_dpdk.c
new file mode 100644
index 0000000..6d16bbe
--- /dev/null
+++ b/platform/linux-dpdk/source/odp_packet_dpdk.c
@@ -0,0 +1,177 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+
+#include <odp_hints.h>
+#include <odp_thread.h>
+
+#include <odp_packet_dpdk.h>
+#include <net/if.h>
+
+/*
+ * RX and TX Prefetch, Host, and Write-back threshold values should be
+ * carefully set for optimal performance. Consult the network
+ * controller's datasheet and supporting DPDK documentation for guidance
+ * on how these parameters should be set.
+ */
+#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
+#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
+#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */
+
+/*
+ * These default values are optimized for use with the Intel(R) 82599 10 GbE
+ * Controller and the DPDK ixgbe PMD. Consider using other values for other
+ * network controllers and/or network drivers.
+ */
+#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */
+#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
+#define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
+
+#define MAX_PKT_BURST 32
+#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
+#define RTE_TEST_RX_DESC_DEFAULT 128
+#define RTE_TEST_TX_DESC_DEFAULT 512
+static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
+static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
+
+static const struct rte_eth_conf port_conf = {
+	.rxmode = {
+		.split_hdr_size = 0,
+		.header_split   = 0, /**< Header Split disabled */
+		.hw_ip_checksum = 0, /**< IP checksum offload disabled */
+		.hw_vlan_filter = 0, /**< VLAN filtering disabled */
+		.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
+		.hw_strip_crc   = 0, /**< CRC stripped by hardware */
+	},
+	.txmode = {
+		.mq_mode = ETH_MQ_TX_NONE,
+	},
+};
+
+static const struct rte_eth_rxconf rx_conf = {
+	.rx_thresh = {
+		.pthresh = RX_PTHRESH,
+		.hthresh = RX_HTHRESH,
+		.wthresh = RX_WTHRESH,
+	},
+};
+
+static const struct rte_eth_txconf tx_conf = {
+	.tx_thresh = {
+		.pthresh = TX_PTHRESH,
+		.hthresh = TX_HTHRESH,
+		.wthresh = TX_WTHRESH,
+	},
+	.tx_free_thresh = 0, /* Use PMD default values */
+	.tx_rs_thresh = 0, /* Use PMD default values */
+	/*
+	 * As the example won't handle mult-segments and offload cases,
+	 * set the flag by default.
+	 */
+	.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS,
+};
+
+int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
+		odp_buffer_pool_t pool)
+{
+	ODP_DBG("setup_pkt_dpdk\n");
+
+	static struct ether_addr eth_addr[RTE_MAX_ETHPORTS];
+	uint8_t portid = 0;
+	uint16_t queueid = 0;
+	int ret;
+	printf("vincent netdev: %s\n", netdev);
+	printf("vincent pool: %lx\n", pool);
+
+	portid = atoi(netdev);
+	pkt_dpdk->portid = portid;
+	pkt_dpdk->queueid = queueid;
+	pkt_dpdk->pool = pool;
+	printf("vincent portid: %u\n", portid);
+
+	fflush(stdout);
+	ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
+	if (ret < 0)
+		ODP_ERR("Cannot configure device: err=%d, port=%u\n",
+			ret, (unsigned) portid);
+
+	rte_eth_macaddr_get(portid, &eth_addr[portid]);
+	ODP_DBG("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
+		(unsigned) portid,
+		eth_addr[portid].addr_bytes[0],
+		eth_addr[portid].addr_bytes[1],
+		eth_addr[portid].addr_bytes[2],
+		eth_addr[portid].addr_bytes[3],
+		eth_addr[portid].addr_bytes[4],
+		eth_addr[portid].addr_bytes[5]);
+
+	/* init one RX queue on each port */
+	fflush(stdout);
+	ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
+				     rte_eth_dev_socket_id(portid), &rx_conf,
+				     (struct rte_mempool *)pool);
+	if (ret < 0)
+		ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n",
+			ret, (unsigned) portid);
+	ODP_DBG("dpdk rx queue setup done\n");
+
+	/* init one TX queue on each port */
+	fflush(stdout);
+	ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
+			rte_eth_dev_socket_id(portid), &tx_conf);
+	if (ret < 0)
+		ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n",
+			ret, (unsigned) portid);
+	ODP_DBG("dpdk tx queue setup done\n");
+
+	/* Start device */
+	ret = rte_eth_dev_start(portid);
+	if (ret < 0)
+		ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n",
+			ret, (unsigned) portid);
+	ODP_DBG("dpdk setup done\n\n");
+
+
+	return 0;
+}
+
+int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk)
+{
+	ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid);
+
+	return 0;
+}
+
+int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
+		unsigned len)
+{
+	return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid,
+				(uint16_t)pkt_dpdk->queueid,
+				(struct rte_mbuf **)pkt_table, (uint16_t)len);
+}
+
+int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
+		unsigned len)
+{
+	return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid,
+				(uint16_t)pkt_dpdk->queueid,
+				(struct rte_mbuf **)pkt_table, (uint16_t)len);
+}
diff --git a/platform/linux-dpdk/source/odp_packet_io.c b/platform/linux-dpdk/source/odp_packet_io.c
new file mode 100644
index 0000000..abea0ec
--- /dev/null
+++ b/platform/linux-dpdk/source/odp_packet_io.c
@@ -0,0 +1,561 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_packet_io.h>
+#include <odp_packet_io_internal.h>
+#include <odp_packet_io_queue.h>
+#include <odp_packet.h>
+#include <odp_packet_internal.h>
+#include <odp_internal.h>
+#include <odp_spinlock.h>
+#include <odp_shared_memory.h>
+#include <odp_packet_socket.h>
+#ifdef ODP_HAVE_NETMAP
+#include <odp_packet_netmap.h>
+#endif
+#include <odp_hints.h>
+#include <odp_config.h>
+#include <odp_queue_internal.h>
+#include <odp_schedule_internal.h>
+#include <odp_debug.h>
+
+#include <odp_pktio_socket.h>
+#ifdef ODP_HAVE_NETMAP
+#include <odp_pktio_netmap.h>
+#endif
+
+#include <string.h>
+
+typedef struct {
+	pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
+} pktio_table_t;
+
+static pktio_table_t *pktio_tbl;
+
+
+static pktio_entry_t *get_entry(odp_pktio_t id)
+{
+	if (odp_unlikely(id == ODP_PKTIO_INVALID ||
+			 id > ODP_CONFIG_PKTIO_ENTRIES))
+		return NULL;
+
+	return &pktio_tbl->entries[id - 1];
+}
+
+int odp_pktio_init_global(void)
+{
+	char name[ODP_QUEUE_NAME_LEN];
+	pktio_entry_t *pktio_entry;
+	queue_entry_t *queue_entry;
+	odp_queue_t qid;
+	int id;
+
+	pktio_tbl = odp_shm_reserve("odp_pktio_entries",
+				    sizeof(pktio_table_t),
+				    sizeof(pktio_entry_t));
+	if (pktio_tbl == NULL)
+		return -1;
+
+	memset(pktio_tbl, 0, sizeof(pktio_table_t));
+
+	for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
+		pktio_entry = get_entry(id);
+
+		odp_spinlock_init(&pktio_entry->s.lock);
+
+		/* Create a default output queue for each pktio resource */
+		snprintf(name, sizeof(name), "%i-pktio_outq_default", (int)id);
+		name[ODP_QUEUE_NAME_LEN-1] = '\0';
+
+		qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, NULL);
+		if (qid == ODP_QUEUE_INVALID)
+			return -1;
+		pktio_entry->s.outq_default = qid;
+
+		queue_entry = queue_to_qentry(qid);
+		queue_entry->s.pktout = id;
+	}
+
+	return 0;
+}
+
+int odp_pktio_init_local(void)
+{
+	return 0;
+}
+
+static int is_free(pktio_entry_t *entry)
+{
+	return (entry->s.taken == 0);
+}
+
+static void set_free(pktio_entry_t *entry)
+{
+	entry->s.taken = 0;
+}
+
+static void set_taken(pktio_entry_t *entry)
+{
+	entry->s.taken = 1;
+}
+
+static void lock_entry(pktio_entry_t *entry)
+{
+	odp_spinlock_lock(&entry->s.lock);
+}
+
+static void unlock_entry(pktio_entry_t *entry)
+{
+	odp_spinlock_unlock(&entry->s.lock);
+}
+
+static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t *params)
+{
+	set_taken(entry);
+	entry->s.inq_default = ODP_QUEUE_INVALID;
+	switch (params->type) {
+	case ODP_PKTIO_TYPE_SOCKET_BASIC:
+	case ODP_PKTIO_TYPE_SOCKET_MMSG:
+	case ODP_PKTIO_TYPE_SOCKET_MMAP:
+		memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock));
+		memset(&entry->s.pkt_sock_mmap, 0,
+		       sizeof(entry->s.pkt_sock_mmap));
+		break;
+#ifdef ODP_HAVE_NETMAP
+	case ODP_PKTIO_TYPE_NETMAP:
+		memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm));
+		break;
+#endif
+	case ODP_PKTIO_TYPE_DPDK:
+		memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk));
+		break;
+	default:
+		ODP_ERR("Packet I/O type not supported. Please recompile\n");
+		break;
+	}
+	/* Save pktio parameters, type is the most useful */
+	memcpy(&entry->s.params, params, sizeof(*params));
+}
+
+static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params)
+{
+	odp_pktio_t id;
+	pktio_entry_t *entry;
+	int i;
+
+	for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
+		entry = &pktio_tbl->entries[i];
+		if (is_free(entry)) {
+			lock_entry(entry);
+			if (is_free(entry)) {
+				init_pktio_entry(entry, params);
+				id = i + 1;
+				return id; /* return with entry locked! */
+			}
+			unlock_entry(entry);
+		}
+	}
+
+	return ODP_PKTIO_INVALID;
+}
+
+static int free_pktio_entry(odp_pktio_t id)
+{
+	pktio_entry_t *entry = get_entry(id);
+
+	if (entry == NULL)
+		return -1;
+
+	set_free(entry);
+
+	return 0;
+}
+
+odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool,
+			   odp_pktio_params_t *params)
+{
+	odp_pktio_t id;
+	pktio_entry_t *pktio_entry;
+	int res;
+
+	if (params == NULL) {
+		ODP_ERR("Invalid pktio params\n");
+		return ODP_PKTIO_INVALID;
+	}
+
+	switch (params->type) {
+	case ODP_PKTIO_TYPE_SOCKET_BASIC:
+	case ODP_PKTIO_TYPE_SOCKET_MMSG:
+	case ODP_PKTIO_TYPE_SOCKET_MMAP:
+		ODP_DBG("Allocating socket pktio\n");
+		break;
+#ifdef ODP_HAVE_NETMAP
+	case ODP_PKTIO_TYPE_NETMAP:
+		ODP_DBG("Allocating netmap pktio\n");
+		break;
+#endif
+	case ODP_PKTIO_TYPE_DPDK:
+		ODP_DBG("Allocating dpdk pktio\n");
+		break;
+	default:
+		ODP_ERR("Invalid pktio type: %02x\n", params->type);
+		return ODP_PKTIO_INVALID;
+	}
+
+	id = alloc_lock_pktio_entry(params);
+	if (id == ODP_PKTIO_INVALID) {
+		ODP_ERR("No resources available.\n");
+		return ODP_PKTIO_INVALID;
+	}
+	/* if successful, alloc_pktio_entry() returns with the entry locked */
+
+	pktio_entry = get_entry(id);
+
+	switch (params->type) {
+	case ODP_PKTIO_TYPE_SOCKET_BASIC:
+	case ODP_PKTIO_TYPE_SOCKET_MMSG:
+		res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, pool);
+		if (res == -1) {
+			close_pkt_sock(&pktio_entry->s.pkt_sock);
+			free_pktio_entry(id);
+			id = ODP_PKTIO_INVALID;
+		}
+		break;
+	case ODP_PKTIO_TYPE_SOCKET_MMAP:
+		res = setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, dev,
+				pool, params->sock_params.fanout);
+		if (res == -1) {
+			close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap);
+			free_pktio_entry(id);
+			id = ODP_PKTIO_INVALID;
+		}
+		break;
+#ifdef ODP_HAVE_NETMAP
+	case ODP_PKTIO_TYPE_NETMAP:
+
+		res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev,
+				pool, &params->nm_params);
+		if (res == -1) {
+			close_pkt_netmap(&pktio_entry->s.pkt_nm);
+			free_pktio_entry(id);
+			id = ODP_PKTIO_INVALID;
+		}
+		break;
+#endif
+	case ODP_PKTIO_TYPE_DPDK:
+		res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, pool);
+		if (res == -1) {
+			close_pkt_dpdk(&pktio_entry->s.pkt_dpdk);
+			free_pktio_entry(id);
+			id = ODP_PKTIO_INVALID;
+		}
+		break;
+	default:
+		free_pktio_entry(id);
+		id = ODP_PKTIO_INVALID;
+		ODP_ERR("Invalid pktio type. Please recompile.\n");
+		break;
+	}
+
+	unlock_entry(pktio_entry);
+	return id;
+}
+
+int odp_pktio_close(odp_pktio_t id)
+{
+	pktio_entry_t *entry;
+	int res = -1;
+
+	entry = get_entry(id);
+	if (entry == NULL)
+		return -1;
+
+	lock_entry(entry);
+	if (!is_free(entry)) {
+		switch (entry->s.params.type) {
+		case ODP_PKTIO_TYPE_SOCKET_BASIC:
+		case ODP_PKTIO_TYPE_SOCKET_MMSG:
+			res  = close_pkt_sock(&entry->s.pkt_sock);
+			break;
+		case ODP_PKTIO_TYPE_SOCKET_MMAP:
+			res  = close_pkt_sock_mmap(&entry->s.pkt_sock_mmap);
+			break;
+#ifdef ODP_HAVE_NETMAP
+		case ODP_PKTIO_TYPE_NETMAP:
+			res  = close_pkt_netmap(&entry->s.pkt_nm);
+			break;
+#endif
+		case ODP_PKTIO_TYPE_DPDK:
+			res  = close_pkt_dpdk(&entry->s.pkt_dpdk);
+			break;
+		default:
+			break;
+		res |= free_pktio_entry(id);
+		}
+	}
+	unlock_entry(entry);
+
+	if (res != 0)
+		return -1;
+
+	return 0;
+}
+
+void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio)
+{
+	odp_packet_hdr(pkt)->input = pktio;
+}
+
+odp_pktio_t odp_pktio_get_input(odp_packet_t pkt)
+{
+	return odp_packet_hdr(pkt)->input;
+}
+
+int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
+{
+	pktio_entry_t *pktio_entry = get_entry(id);
+	int pkts;
+	int i;
+
+	if (pktio_entry == NULL)
+		return -1;
+
+	lock_entry(pktio_entry);
+	switch (pktio_entry->s.params.type) {
+	case ODP_PKTIO_TYPE_SOCKET_BASIC:
+		pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock,
+				pkt_table, len);
+		break;
+	case ODP_PKTIO_TYPE_SOCKET_MMSG:
+		pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
+				pkt_table, len);
+		break;
+	case ODP_PKTIO_TYPE_SOCKET_MMAP:
+		pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
+				pkt_table, len);
+		break;
+#ifdef ODP_HAVE_NETMAP
+	case ODP_PKTIO_TYPE_NETMAP:
+		pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm, pkt_table, len);
+		break;
+#endif
+	case ODP_PKTIO_TYPE_DPDK:
+		pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, len);
+		break;
+	default:
+		pkts = -1;
+		break;
+	}
+
+	unlock_entry(pktio_entry);
+	if (pkts < 0)
+		return pkts;
+
+	for (i = 0; i < pkts; ++i)
+		odp_pktio_set_input(pkt_table[i], id);
+
+	return pkts;
+}
+
+int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
+{
+	pktio_entry_t *pktio_entry = get_entry(id);
+	int pkts;
+
+	if (pktio_entry == NULL)
+		return -1;
+
+	lock_entry(pktio_entry);
+	switch (pktio_entry->s.params.type) {
+	case ODP_PKTIO_TYPE_SOCKET_BASIC:
+		pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock,
+				pkt_table, len);
+		break;
+	case ODP_PKTIO_TYPE_SOCKET_MMSG:
+		pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock,
+				pkt_table, len);
+		break;
+	case ODP_PKTIO_TYPE_SOCKET_MMAP:
+		pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap,
+				pkt_table, len);
+		break;
+#ifdef ODP_HAVE_NETMAP
+	case ODP_PKTIO_TYPE_NETMAP:
+		pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm,
+				pkt_table, len);
+		break;
+#endif
+	case ODP_PKTIO_TYPE_DPDK:
+		pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk,
+				pkt_table, len);
+		break;
+	default:
+		pkts = -1;
+	}
+	unlock_entry(pktio_entry);
+
+	return pkts;
+}
+
+int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue)
+{
+	pktio_entry_t *pktio_entry = get_entry(id);
+	queue_entry_t *qentry = queue_to_qentry(queue);
+
+	if (pktio_entry == NULL || qentry == NULL)
+		return -1;
+
+	if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN)
+		return -1;
+
+	lock_entry(pktio_entry);
+	pktio_entry->s.inq_default = queue;
+	unlock_entry(pktio_entry);
+
+	queue_lock(qentry);
+	qentry->s.pktin = id;
+	qentry->s.status = QUEUE_STATUS_SCHED;
+	queue_unlock(qentry);
+
+	odp_schedule_queue(queue, qentry->s.param.sched.prio);
+
+	return 0;
+}
+
+int odp_pktio_inq_remdef(odp_pktio_t id)
+{
+	return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID);
+}
+
+odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id)
+{
+	pktio_entry_t *pktio_entry = get_entry(id);
+
+	if (pktio_entry == NULL)
+		return ODP_QUEUE_INVALID;
+
+	return pktio_entry->s.inq_default;
+}
+
+odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id)
+{
+	pktio_entry_t *pktio_entry = get_entry(id);
+
+	if (pktio_entry == NULL)
+		return ODP_QUEUE_INVALID;
+
+	return pktio_entry->s.outq_default;
+}
+
+int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
+{
+	odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t) buf_hdr);
+	int len = 1;
+	int nbr;
+
+	nbr = odp_pktio_send(qentry->s.pktout, &pkt, len);
+	return (nbr == len ? 0 : -1);
+}
+
+odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry)
+{
+	(void)qentry;
+	return NULL;
+}
+
+int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
+		     int num)
+{
+	odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
+	int nbr;
+	int i;
+
+	for (i = 0; i < num; ++i)
+		pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t) buf_hdr[i]);
+
+	nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num);
+	return (nbr == num ? 0 : -1);
+}
+
+int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[],
+		     int num)
+{
+	(void)qentry;
+	(void)buf_hdr;
+	(void)num;
+
+	return 0;
+}
+
+int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr)
+{
+	/* Use default action */
+	return queue_enq(qentry, buf_hdr);
+}
+
+odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
+{
+	odp_buffer_hdr_t *buf_hdr;
+
+	buf_hdr = queue_deq(qentry);
+
+	if (buf_hdr == NULL) {
+		odp_packet_t pkt;
+		odp_buffer_t buf;
+		odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
+		odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
+		int pkts, i, j;
+
+		pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
+				      QUEUE_MULTI_MAX);
+
+		if (pkts > 0) {
+			pkt = pkt_tbl[0];
+			buf = odp_buffer_from_packet(pkt);
+			buf_hdr = odp_buf_to_hdr(buf);
+
+			for (i = 1, j = 0; i < pkts; ++i) {
+				buf = odp_buffer_from_packet(pkt_tbl[i]);
+				tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf);
+			}
+			queue_enq_multi(qentry, tmp_hdr_tbl, j);
+		}
+	}
+
+	return buf_hdr;
+}
+
+int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
+{
+	/* Use default action */
+	return queue_enq_multi(qentry, buf_hdr, num);
+}
+
+int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
+{
+	int nbr;
+
+	nbr = queue_deq_multi(qentry, buf_hdr, num);
+
+	if (nbr < num) {
+		odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
+		odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
+		odp_buffer_t buf;
+		int pkts, i;
+
+		pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl,
+				      QUEUE_MULTI_MAX);
+		if (pkts > 0) {
+			for (i = 0; i < pkts; ++i) {
+				buf = odp_buffer_from_packet(pkt_tbl[i]);
+				tmp_hdr_tbl[i] = odp_buf_to_hdr(buf);
+			}
+			queue_enq_multi(qentry, tmp_hdr_tbl, pkts);
+		}
+	}
+
+	return nbr;
+}
diff --git a/platform/linux-dpdk/source/odp_queue.c b/platform/linux-dpdk/source/odp_queue.c
new file mode 100644
index 0000000..554b8ea
--- /dev/null
+++ b/platform/linux-dpdk/source/odp_queue.c
@@ -0,0 +1,435 @@ 
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_queue.h>
+#include <odp_queue_internal.h>
+#include <odp_std_types.h>
+#include <odp_align.h>
+#include <odp_buffer.h>
+#include <odp_buffer_internal.h>
+#include <odp_buffer_pool_internal.h>
+#include <odp_internal.h>
+#include <odp_shared_memory.h>
+#include <odp_schedule_internal.h>
+#include <odp_config.h>
+#include <odp_packet_io_internal.h>
+#include <odp_packet_io_queue.h>
+#include <odp_debug.h>
+#include <odp_hints.h>
+
+#ifdef USE_TICKETLOCK
+#include <odp_ticketlock.h>
+#define LOCK(a)      odp_ticketlock_lock(a)
+#define UNLOCK(a)    odp_ticketlock_unlock(a)
+#define LOCK_INIT(a) odp_ticketlock_init(a)
+#else
+#include <odp_spinlock.h>
+#define LOCK(a)      odp_spinlock_lock(a)
+#define UNLOCK(a)    odp_spinlock_unlock(a)
+#define LOCK_INIT(a) odp_spinlock_init(a)
+#endif
+
+#include <string.h>
+
+
+typedef struct queue_table_t {
+	queue_entry_t  queue[ODP_CONFIG_QUEUES];
+} queue_table_t;
+
+static queue_table_t *queue_tbl;
+
+
+queue_entry_t *get_qentry(uint32_t queue_id)
+{
+	return &queue_tbl->queue[queue_id];
+}
+
+static void queue_init(queue_entry_t *queue, const char *name,
+		       odp_queue_type_t type, odp_queue_param_t *param)
+{
+	strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1);
+	queue->s.type = type;
+
+	if (param) {
+		memcpy(&queue->s.param, param, sizeof(odp_queue_param_t));
+	} else {
+		/* Defaults */
+		memset(&queue->s.param, 0, sizeof(odp_queue_param_t));
+		queue->s.param.sched.prio  = ODP_SCHED_PRIO_DEFAULT;
+		queue->s.param.sched.sync  = ODP_SCHED_SYNC_DEFAULT;
+		queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT;
+	}
+
+	switch (type) {
+	case ODP_QUEUE_TYPE_PKTIN:
+		queue->s.enqueue = pktin_enqueue;
+		queue->s.dequeue = pktin_dequeue;
+		queue->s.enqueue_multi = pktin_enq_multi;
+		queue->s.dequeue_multi = pktin_deq_multi;
+		break;
+	case ODP_QUEUE_TYPE_PKTOUT:
+		queue->s.enqueue = pktout_enqueue;
+		queue->s.dequeue = pktout_dequeue;
+		queue->s.enqueue_multi = pktout_enq_multi;
+		queue->s.dequeue_multi = pktout_deq_multi;
+		break;
+	default:
+		queue->s.enqueue = queue_enq;
+		queue->s.dequeue = queue_deq;
+		queue->s.enqueue_multi = queue_enq_multi;
+		queue->s.dequeue_multi = queue_deq_multi;
+		break;
+	}
+
+	queue->s.head = NULL;
+	queue->s.tail = NULL;
+	queue->s.sched_buf = ODP_BUFFER_INVALID;
+}
+
+
+int odp_queue_init_global(void)
+{
+	uint32_t i;
+
+	ODP_DBG("Queue init ... ");
+
+	queue_tbl = odp_shm_reserve("odp_queues",
+				    sizeof(queue_table_t),
+				    sizeof(queue_entry_t));
+
+	if (queue_tbl == NULL)
+		return -1;
+
+	memset(queue_tbl, 0, sizeof(queue_table_t));
+
+	for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
+		/* init locks */
+		queue_entry_t *queue = get_qentry(i);
+		LOCK_INIT(&queue->s.lock);
+		queue->s.handle = queue_from_id(i);
+	}
+
+	ODP_DBG("done\n");
+	ODP_DBG("Queue init global\n");
+	ODP_DBG("  struct queue_entry_s size %zu\n",
+		sizeof(struct queue_entry_s));
+	ODP_DBG("  queue_entry_t size        %zu\n",
+		sizeof(queue_entry_t));
+	ODP_DBG("\n");
+
+	return 0;
+}
+
+odp_queue_type_t odp_queue_type(odp_queue_t handle)
+{
+	queue_entry_t *queue;
+
+	queue = queue_to_qentry(handle);
+
+	return queue->s.type;
+}
+
+odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle)
+{
+	queue_entry_t *queue;
+
+	queue = queue_to_qentry(handle);
+
+	return queue->s.param.sched.sync;
+}
+
+odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
+			     odp_queue_param_t *param)
+{
+	uint32_t i;
+	queue_entry_t *queue;
+	odp_queue_t handle = ODP_QUEUE_INVALID;
+
+	for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
+		queue = &queue_tbl->queue[i];
+
+		if (queue->s.status != QUEUE_STATUS_FREE)
+			continue;
+
+		LOCK(&queue->s.lock);
+		if (queue->s.status == QUEUE_STATUS_FREE) {
+			queue_init(queue, name, type, param);
+
+			if (type == ODP_QUEUE_TYPE_SCHED ||
+			    type == ODP_QUEUE_TYPE_PKTIN)
+				queue->s.status = QUEUE_STATUS_NOTSCHED;
+			else
+				queue->s.status = QUEUE_STATUS_READY;
+
+			handle = queue->s.handle;
+			UNLOCK(&queue->s.lock);
+			break;
+		}
+		UNLOCK(&queue->s.lock);
+	}
+
+	if (handle != ODP_QUEUE_INVALID &&
+	    (type == ODP_QUEUE_TYPE_SCHED || type == ODP_QUEUE_TYPE_PKTIN)) {
+		odp_buffer_t buf;
+
+		buf = odp_schedule_buffer_alloc(handle);
+		if (buf == ODP_BUFFER_INVALID) {
+			ODP_ERR("queue_init: sched buf alloc failed\n");
+			return ODP_QUEUE_INVALID;
+		}
+
+		queue->s.sched_buf = buf;
+		odp_schedule_mask_set(handle, queue->s.param.sched.prio);
+	}
+
+	return handle;
+}
+
+
+odp_buffer_t queue_sched_buf(odp_queue_t handle)
+{
+	queue_entry_t *queue;
+	queue = queue_to_qentry(handle);
+
+	return queue->s.sched_buf;
+}
+
+
+int queue_sched_atomic(odp_queue_t handle)
+{
+	queue_entry_t *queue;
+	queue = queue_to_qentry(handle);
+
+	return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC;
+}
+
+
+odp_queue_t odp_queue_lookup(const char *name)
+{
+	uint32_t i;
+
+	for (i = 0; i < ODP_CONFIG_QUEUES; i++) {
+		queue_entry_t *queue = &queue_tbl->queue[i];
+
+		if (queue->s.status == QUEUE_STATUS_FREE)
+			continue;
+
+		LOCK(&queue->s.lock);
+		if (strcmp(name, queue->s.name) == 0) {
+			/* found it */
+			UNLOCK(&queue->s.lock);
+			return queue->s.handle;
+		}
+		UNLOCK(&queue->s.lock);
+	}
+
+	return ODP_QUEUE_INVALID;
+}
+
+
+int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
+{
+	int sched = 0;
+
+	LOCK(&queue->s.lock);
+	if (queue->s.head == NULL) {
+		/* Empty queue */
+		queue->s.head = buf_hdr;
+		queue->s.tail = buf_hdr;
+		buf_hdr->pkt.next = NULL;
+	} else {
+		queue->s.tail->pkt.next = buf_hdr;
+		queue->s.tail = buf_hdr;
+		buf_hdr->pkt.next = NULL;
+	}
+
+	if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
+		queue->s.status = QUEUE_STATUS_SCHED;
+		sched = 1; /* retval: schedule queue */
+	}
+	UNLOCK(&queue->s.lock);
+
+	/* Add queue to scheduling */
+	if (sched == 1)
+		odp_schedule_queue(queue->s.handle, queue->s.param.sched.prio);
+
+	return 0;
+}
+
+
+int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], int num)
+{
+	int sched = 0;
+	int i;
+	odp_buffer_hdr_t *tail;
+
+	for (i = 0; i < num - 1; i++)
+		buf_hdr[i]->pkt.next = buf_hdr[i+1];
+
+	tail = buf_hdr[num-1];
+	buf_hdr[num-1]->pkt.next = NULL;
+
+	LOCK(&queue->s.lock);
+	/* Empty queue */
+	if (queue->s.head == NULL)
+		queue->s.head = buf_hdr[0];
+	else
+		queue->s.tail->pkt.next = buf_hdr[0];
+
+	queue->s.tail = tail;
+
+	if (queue->s.status == QUEUE_STATUS_NOTSCHED) {
+		queue->s.status = QUEUE_STATUS_SCHED;
+		sched = 1; /* retval: schedule queue */
+	}
+	UNLOCK(&queue->s.lock);
+
+	/* Add queue to scheduling */
+	if (sched == 1)
+		odp_schedule_queue(queue->s.handle, queue->s.param.sched.prio);
+
+	return 0;
+}
+
+
+int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int num)
+{
+	odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
+	queue_entry_t *queue;
+	int i;
+
+	if (num > QUEUE_MULTI_MAX)
+		num = QUEUE_MULTI_MAX;
+
+	queue = queue_to_qentry(handle);
+
+	for (i = 0; i < num; i++)
+		buf_hdr[i] = odp_buf_to_hdr(buf[i]);
+
+	return queue->s.enqueue_multi(queue, buf_hdr, num);
+}
+
+
+int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf)
+{
+	odp_buffer_hdr_t *buf_hdr;
+	queue_entry_t *queue;
+
+	queue   = queue_to_qentry(handle);
+	buf_hdr = odp_buf_to_hdr(buf);
+
+	return queue->s.enqueue(queue, buf_hdr);
+}
+
+
+odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
+{
+	odp_buffer_hdr_t *buf_hdr = NULL;
+
+	LOCK(&queue->s.lock);
+
+	if (queue->s.head == NULL) {
+		/* Already empty queue */
+		if (queue->s.status == QUEUE_STATUS_SCHED &&
+		    queue->s.type != ODP_QUEUE_TYPE_PKTIN)
+			queue->s.status = QUEUE_STATUS_NOTSCHED;
+	} else {
+		buf_hdr       = queue->s.head;
+		queue->s.head = buf_hdr->pkt.next;
+		buf_hdr->pkt.next = NULL;
+
+		if (queue->s.head == NULL) {
+			/* Queue is now empty */
+			queue->s.tail = NULL;
+		}
+	}
+
+	UNLOCK(&queue->s.lock);
+
+	return buf_hdr;
+}
+
+
+int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], int num)
+{
+	int i = 0;
+
+	LOCK(&queue->s.lock);
+
+	if (queue->s.head == NULL) {
+		/* Already empty queue */
+		if (queue->s.status == QUEUE_STATUS_SCHED &&
+		    queue->s.type != ODP_QUEUE_TYPE_PKTIN)
+			queue->s.status = QUEUE_STATUS_NOTSCHED;
+	} else {
+		odp_buffer_hdr_t *hdr = queue->s.head;
+
+		for (; i < num && hdr; i++) {
+			buf_hdr[i]       = hdr;
+			/* odp_prefetch(hdr->addr); */
+			hdr              = hdr->pkt.next;
+			buf_hdr[i]->pkt.next = NULL;
+		}
+
+		queue->s.head = hdr;
+
+		if (hdr == NULL) {
+			/* Queue is now empty */
+			queue->s.tail = NULL;
+		}
+	}
+
+	UNLOCK(&queue->s.lock);
+
+	return i;
+}
+
+
+int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int num)
+{
+	queue_entry_t *queue;
+	odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX];
+	int i, ret;
+
+	if (num > QUEUE_MULTI_MAX)
+		num = QUEUE_MULTI_MAX;
+
+	queue = queue_to_qentry(handle);
+
+	ret = queue->s.dequeue_multi(queue, buf_hdr, num);
+
+	for (i = 0; i < ret; i++)
+		buf[i] = (odp_buffer_t) buf_hdr[i];
+
+	return ret;
+}
+
+
+odp_buffer_t odp_queue_deq(odp_queue_t handle)
+{
+	queue_entry_t *queue;
+	odp_buffer_hdr_t *buf_hdr;
+
+	queue   = queue_to_qentry(handle);
+	buf_hdr = queue->s.dequeue(queue);
+
+	if (buf_hdr)
+		return (odp_buffer_t) buf_hdr;
+
+	return ODP_BUFFER_INVALID;
+}
+
+
+void queue_lock(queue_entry_t *queue)
+{
+	LOCK(&queue->s.lock);
+}
+
+
+void queue_unlock(queue_entry_t *queue)
+{
+	UNLOCK(&queue->s.lock);
+}