diff mbox

[v4,1/2] Initial odp-dpdk port

Message ID 20140717102514.GA18656@8470w
State New
Headers show

Commit Message

Anders Roxell July 17, 2014, 10:25 a.m. UTC
Hi Venkatesh,

I've started to look into your patches.

I haven't reviewed all, just started.

On 2014-07-16 15:53, venkatesh.vivekanandan@linaro.org wrote:
> From: Vincent Hsu <vincent.hsu@linaro.org>
> 
> Signed-off-by: Vincent Hsu <vincent.hsu@linaro.org>
> 
> - Add/modify files to support linux-dpdk compilation in new automake
>   environment.
> 	* Modified configure.ac
> 	* Added platform/linux-dpdk/Makefile.am
> 	* Moved all files from platform/linux-dpdk/source to
> 	  platform/linux-dpdk/.
> 
> - Added platform/linux-dpdk/README on how to clone, compile DPDK and
>   commands to execute on ODP.
> - Made ODP_BUFFER_<TYPES> consistent with linux-generic.
> - Removed odp_buffer_is_scatter API to be inline with linux-generic.
> - Added platform/linux-dpdk/odp_linux.c to supply the function
>   and argument to the pthread created by dpdk.
> 
> Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org>
> ---
>  configure.ac                                       |   2 +
>  platform/linux-dpdk/Makefile.am                    | 100 ++++
>  platform/linux-dpdk/README                         |  70 +++
>  platform/linux-dpdk/include/api/odp_buffer.h       |  94 ++++
>  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  |  72 +++
>  .../linux-dpdk/include/odp_buffer_pool_internal.h  |  90 ++++
>  platform/linux-dpdk/include/odp_packet_dpdk.h      |  87 ++++
>  platform/linux-dpdk/include/odp_packet_internal.h  | 139 +++++
>  .../linux-dpdk/include/odp_packet_io_internal.h    |  51 ++
>  platform/linux-dpdk/odp_buffer.c                   |  90 ++++
>  platform/linux-dpdk/odp_buffer_pool.c              | 156 ++++++
>  platform/linux-dpdk/odp_init.c                     | 113 +++++
>  platform/linux-dpdk/odp_linux.c                    |  96 ++++
>  platform/linux-dpdk/odp_packet.c                   | 374 ++++++++++++++
>  platform/linux-dpdk/odp_packet_dpdk.c              | 189 +++++++
>  platform/linux-dpdk/odp_packet_io.c                | 561 +++++++++++++++++++++

I did a diff between this file and
platform/linux-generic/odp_packet_io.c and basically the only changes
that is are 6 case for ODP_PKTIO_TYPE_DPDK, is it possible to factorise
this somehow so we don't need to copy this much code?
I haven't looked in any other files.

>  platform/linux-dpdk/odp_queue.c                    | 435 ++++++++++++++++
>  20 files changed, 3091 insertions(+)
>  create mode 100644 platform/linux-dpdk/Makefile.am
>  create mode 100644 platform/linux-dpdk/README
>  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/odp_buffer.c
>  create mode 100644 platform/linux-dpdk/odp_buffer_pool.c
>  create mode 100644 platform/linux-dpdk/odp_init.c
>  create mode 100644 platform/linux-dpdk/odp_linux.c
>  create mode 100644 platform/linux-dpdk/odp_packet.c
>  create mode 100644 platform/linux-dpdk/odp_packet_dpdk.c
>  create mode 100644 platform/linux-dpdk/odp_packet_io.c
>  create mode 100644 platform/linux-dpdk/odp_queue.c
> 
> diff --git a/configure.ac b/configure.ac
> index 873ea9e..3d8481f 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -51,6 +51,7 @@ AC_ARG_WITH([platform],
>  
>  AM_CONDITIONAL([ODP_PLATFORM_GENERIC], [test "x$with_platform" = xlinux-generic])
>  AM_CONDITIONAL([ODP_PLATFORM_KEYSTONE2], [test "x$with_platform" = xlinux-keystone2])
> +AM_CONDITIONAL([ODP_PLATFORM_DPDK], [test "x$with_platform" = xlinux-dpdk])
>  
>  AC_SUBST([with_platform])
>  
> @@ -111,6 +112,7 @@ AC_CONFIG_FILES([Makefile
>  		 platform/Makefile
>  		 platform/linux-generic/Makefile
>  		 platform/linux-keystone2/Makefile
> +		 platform/linux-dpdk/Makefile
>  		 test/Makefile
>  		 test/api_test/Makefile
>  		 test/example/Makefile
> diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am
> new file mode 100644
> index 0000000..067c0bb
> --- /dev/null
> +++ b/platform/linux-dpdk/Makefile.am
> @@ -0,0 +1,100 @@
> +include $(top_srcdir)/Makefile.inc
> +LIB   = $(top_builddir)/lib
> +
> +dist_pkgdata_DATA = $(LIB)/libodp.la
> +
> +pkgconfigdir = pkgconfig
> +nodist_pkgconfig_DATA = $(top_builddir)/pkgconfig/libodp.pc
> +
> +.PHONY: pkgconfig/libodp.pc
> +
> +RTE_SDK    ?= $(top_srcdir)/../dpdk
> +RTE_OUTPUT ?= $(RTE_SDK)/build
> +RTE_LIB    ?= $(RTE_OUTPUT)/lib
> +
> +PLAT_CFLAGS  = -include $(RTE_OUTPUT)/include/rte_config.h

why do you need to specify this like that?

> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include
> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch
> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env

Remove this... too hardcoded... do as ks2

Something like this:
$ ./configure --with-platform=linux-dpdk
LDFLAGS=-L/home/anders/src/dpdk/build/lib CFLAGS="-include
/home/anders/src/for_dpdk/build/include/rte_config.h
-I/home/anders/src/for_dpdk/build/include
-I/home/anders/src/for_dpdk/build/include/arch
-I/home/anders/src/for_dpdk/build/include/exec-env"

I used build instead of my_sdk_build_dir that was stated in the README


$ gitt df
> +
> +$ cd ./dpdk
> +# Only for the first time
> +$ make config T=x86_64-default-linuxapp-gcc O=my_sdk_build_dir

The O= you should be able to set that to whatever you want right?

s|my_sdk_build_dir|<abs/path/to/dpdk/build/dir>|

> +set CONFIG_RTE_BUILD_COMBINE_LIBS=y in my_sdk_build_dir/.config

Maybe change s|set|# set|

> +
> +Note: If not-intel SFP's are used in NIC, then go to my_sdk_build_dir/.config and set CONFIG_RTE_LIBRTE_IXGBE_ALLOW_UNSUPPORTED_SFP=y
> +
> +$ cd my_sdk_build_dir/

s|my_sdk_build_dir|<abs/path/to/dpdk/build/dir>|

> +$ make clean; make
> +
> +# To reserve huge pages which is needed for dpdk execute following command
> +$ echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
> +# If you are running on a multi-node machine then, hugepages should be reserved on each node
> +$ echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
> +
> +$ sudo mkdir /mnt/huge
> +$ sudo mount -t hugetlbfs nodev /mnt/huge
> +# To load uio driver
> +$ sudo /sbin/modprobe uio
> +$ ulimit -Sn 2048
> +
> +# sudo insmod igb_uio.ko
> +$ cd ./dpdk
> +$ insmod ./build/build/lib/librte_eal/linuxapp/igb_uio/igb_uio.ko
> +
> +$ rmmod ixgbe
> +$ modprobe ixgbe
> +# If the SFP's used are non-intel, then
> +$ modprobe ixgbe allow_unsupported_sfp=1
> +
> +$ cd ./dpdk
> +$ ./tools/igb_uio_bind.py --status
> +
> +Now you should look for pci id listed and give it in the following command in
> +place of 42:00.0
> +
> +# To give the interfaces to dpdk, use following command
> +$ sudo ./tools/igb_uio_bind.py --bind=igb_uio 42:00.0
> +$ sudo ./tools/igb_uio_bind.py --bind=igb_uio 42:00.1
> +# To restore it back to kernel, use following command
> +$ sudo ./tools/igb_uio_bind.py --bind=ixgbe 42:00.0
> +$ sudo ./tools/igb_uio_bind.py --bind=ixgbe 42:00.1
> +
> +# To compile ODP with linux-dpdk
> +$ ./bootstrap
> +$ ./configure --with-platform=linux-dpdk

And maybe add to the ./configure command:
LDFLAGS=-L<dpdk-build-dir>/lib CFLAGS="-include
<dpdk-build-dir>/include/rte_config.h
-I<dpdk-build-dir>/include
-I<dpdk-build-dir>/include/arch
-I<dpdk-build-dir>/include/exec-env"

Cheers,
Anders

> +$ make clean
> +$ make
> +
> +# Commands to test
> +l2fwding app - ./test/l2fwd/odp_l2fwd -i 0,1 -t 5 -m 0 -c 2
> +loopback app - ./test/packet/odp_pktio -i 0,1 -t 5 -m 0 -c 2
> +
> +	-i 0,1 - interface number
> +	-t 5   - dpdk type
> +	-m 0   - burst mode
> +	-c 2   - number of cpus
> 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..9ea1ed8
> --- /dev/null
> +++ b/platform/linux-dpdk/include/api/odp_buffer.h
> @@ -0,0 +1,94 @@
> +/* 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_ANY       0  /**< Buffer that can hold any other
> +					  buffer type */
> +#define ODP_BUFFER_TYPE_RAW       1  /**< Raw buffer, no additional metadata */
> +#define ODP_BUFFER_TYPE_PACKET    2  /**< Packet buffer */
> +#define ODP_BUFFER_TYPE_TIMEOUT   3  /**< Timeout buffer */
> +
> +/**
> + * 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..f87ec80
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_buffer_internal.h
> @@ -0,0 +1,72 @@
> +/* 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..bcbe9e8
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
> @@ -0,0 +1,87 @@
> +/* 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..0f798c1
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_packet_internal.h
> @@ -0,0 +1,139 @@
> +/* 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..08abea7
> --- /dev/null
> +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
> @@ -0,0 +1,51 @@
> +/* 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/odp_buffer.c b/platform/linux-dpdk/odp_buffer.c
> new file mode 100644
> index 0000000..e2f8942
> --- /dev/null
> +++ b/platform/linux-dpdk/odp_buffer.c
> @@ -0,0 +1,90 @@
> +/* 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_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/odp_buffer_pool.c b/platform/linux-dpdk/odp_buffer_pool.c
> new file mode 100644
> index 0000000..de90275
> --- /dev/null
> +++ b/platform/linux-dpdk/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/odp_init.c b/platform/linux-dpdk/odp_init.c
> new file mode 100644
> index 0000000..ecc2066
> --- /dev/null
> +++ b/platform/linux-dpdk/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/odp_linux.c b/platform/linux-dpdk/odp_linux.c
> new file mode 100644
> index 0000000..067bd99
> --- /dev/null
> +++ b/platform/linux-dpdk/odp_linux.c
> @@ -0,0 +1,96 @@
> +/* Copyright (c) 2013, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif
> +#include <sched.h>
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <assert.h>
> +
> +#include <helper/odp_linux.h>
> +#include <odp_internal.h>
> +#include <odp_thread.h>
> +#include <odp_init.h>
> +#include <odp_system_info.h>
> +
> +#include <rte_lcore.h>
> +
> +typedef struct {
> +	int thr_id;
> +	void *(*start_routine) (void *);
> +	void *arg;
> +
> +} odp_start_args_t;
> +
> +
> +static void *odp_run_start_routine(void *arg)
> +{
> +	odp_start_args_t *start_args = arg;
> +
> +	/* ODP thread local init */
> +	odp_init_local(start_args->thr_id);
> +
> +	return start_args->start_routine(start_args->arg);
> +}
> +
> +
> +void odp_linux_pthread_create(odp_linux_pthread_t *thread_tbl, int num,
> +		int first_core, void *(*start_routine) (void *), void *arg)
> +{
> +	int i;
> +	cpu_set_t cpu_set;
> +	odp_start_args_t *start_args;
> +	int core_count;
> +	int cpu;
> +
> +	(void) cpu_set;
> +	(void) thread_tbl;
> +
> +	core_count = odp_sys_core_count();
> +
> +	assert((first_core >= 0) && (first_core < core_count));
> +	assert((num >= 0) && (num <= core_count));
> +
> +	for (i = 0; i < num; i++) {
> +		cpu = (first_core + i) % core_count;
> +
> +		start_args = malloc(sizeof(odp_start_args_t));
> +		memset(start_args, 0, sizeof(odp_start_args_t));
> +		start_args->start_routine = start_routine;
> +		start_args->arg           = arg;
> +
> +		odp_thread_create(cpu);
> +		start_args->thr_id = cpu;
> +		/* If not master core */
> +		if (cpu != 0) {
> +			rte_eal_remote_launch(
> +				(int(*)(void *))odp_run_start_routine,
> +				start_args, cpu);
> +		} else {
> +			lcore_config[cpu].ret = (int)(uint64_t)
> +				odp_run_start_routine(start_args);
> +			lcore_config[cpu].state = FINISHED;
> +		}
> +	}
> +}
> +
> +
> +void odp_linux_pthread_join(odp_linux_pthread_t *thread_tbl, int num)
> +{
> +	uint32_t lcore_id;
> +
> +	(void) thread_tbl;
> +	(void) num;
> +
> +	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
> +	if (rte_eal_wait_lcore(lcore_id) < 0)
> +		return;
> +	}
> +}
> diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c
> new file mode 100644
> index 0000000..c34e626
> --- /dev/null
> +++ b/platform/linux-dpdk/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/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c
> new file mode 100644
> index 0000000..31bfa30
> --- /dev/null
> +++ b/platform/linux-dpdk/odp_packet_dpdk.c
> @@ -0,0 +1,189 @@
> +/* 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 16
> +#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("dpdk netdev: %s\n", netdev);
> +	printf("dpdk pool: %lx\n", pool);
> +
> +	portid = atoi(netdev);
> +	pkt_dpdk->portid = portid;
> +	pkt_dpdk->queueid = queueid;
> +	pkt_dpdk->pool = pool;
> +	printf("dpdk 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)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t nb_rx, i = 0;
> +
> +	memset(pkts_burst, 0 , sizeof(pkts_burst));
> +	nb_rx = rte_eth_rx_burst((uint8_t)pkt_dpdk->portid,
> +				 (uint16_t)pkt_dpdk->queueid,
> +				 (struct rte_mbuf **)pkts_burst, (uint16_t)len);
> +	for (i = 0; i < nb_rx; i++)
> +		pkt_table[i] = (odp_packet_t)pkts_burst[i];
> +	return nb_rx;
> +}
> +
> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
> +		unsigned len)
> +{
> +	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> +	uint16_t i;
> +
> +	for (i = 0; i < len; i++)
> +		pkts_burst[i] = (struct rte_mbuf *)pkt_table[i];
> +	return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid,
> +				(uint16_t)pkt_dpdk->queueid,
> +				(struct rte_mbuf **)pkts_burst, (uint16_t)len);
> +}
> diff --git a/platform/linux-dpdk/odp_packet_io.c b/platform/linux-dpdk/odp_packet_io.c
> new file mode 100644
> index 0000000..abea0ec
> --- /dev/null
> +++ b/platform/linux-dpdk/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/odp_queue.c b/platform/linux-dpdk/odp_queue.c
> new file mode 100644
> index 0000000..554b8ea
> --- /dev/null
> +++ b/platform/linux-dpdk/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.8.1.2
> 
> 
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp

Comments

Venkatesh Vivekanandan July 18, 2014, 5:42 a.m. UTC | #1
On 17 July 2014 15:55, Anders Roxell <anders.roxell@linaro.org> wrote:

> Hi Venkatesh,
>
> I've started to look into your patches.
>
> I haven't reviewed all, just started.
>
> On 2014-07-16 15:53, venkatesh.vivekanandan@linaro.org wrote:
> > From: Vincent Hsu <vincent.hsu@linaro.org>
> >
> > Signed-off-by: Vincent Hsu <vincent.hsu@linaro.org>
> >
> > - Add/modify files to support linux-dpdk compilation in new automake
> >   environment.
> >       * Modified configure.ac
> >       * Added platform/linux-dpdk/Makefile.am
> >       * Moved all files from platform/linux-dpdk/source to
> >         platform/linux-dpdk/.
> >
> > - Added platform/linux-dpdk/README on how to clone, compile DPDK and
> >   commands to execute on ODP.
> > - Made ODP_BUFFER_<TYPES> consistent with linux-generic.
> > - Removed odp_buffer_is_scatter API to be inline with linux-generic.
> > - Added platform/linux-dpdk/odp_linux.c to supply the function
> >   and argument to the pthread created by dpdk.
> >
> > Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org
> >
> > ---
> >  configure.ac                                       |   2 +
> >  platform/linux-dpdk/Makefile.am                    | 100 ++++
> >  platform/linux-dpdk/README                         |  70 +++
> >  platform/linux-dpdk/include/api/odp_buffer.h       |  94 ++++
> >  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  |  72 +++
> >  .../linux-dpdk/include/odp_buffer_pool_internal.h  |  90 ++++
> >  platform/linux-dpdk/include/odp_packet_dpdk.h      |  87 ++++
> >  platform/linux-dpdk/include/odp_packet_internal.h  | 139 +++++
> >  .../linux-dpdk/include/odp_packet_io_internal.h    |  51 ++
> >  platform/linux-dpdk/odp_buffer.c                   |  90 ++++
> >  platform/linux-dpdk/odp_buffer_pool.c              | 156 ++++++
> >  platform/linux-dpdk/odp_init.c                     | 113 +++++
> >  platform/linux-dpdk/odp_linux.c                    |  96 ++++
> >  platform/linux-dpdk/odp_packet.c                   | 374 ++++++++++++++
> >  platform/linux-dpdk/odp_packet_dpdk.c              | 189 +++++++
> >  platform/linux-dpdk/odp_packet_io.c                | 561
> +++++++++++++++++++++
>
> I did a diff between this file and
> platform/linux-generic/odp_packet_io.c and basically the only changes
> that is are 6 case for ODP_PKTIO_TYPE_DPDK, is it possible to factorise
> this somehow so we don't need to copy this much code?
> I haven't looked in any other files.
>

I cleaned up this file and sent v5.


>
> >  platform/linux-dpdk/odp_queue.c                    | 435
> ++++++++++++++++
> >  20 files changed, 3091 insertions(+)
> >  create mode 100644 platform/linux-dpdk/Makefile.am
> >  create mode 100644 platform/linux-dpdk/README
> >  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/odp_buffer.c
> >  create mode 100644 platform/linux-dpdk/odp_buffer_pool.c
> >  create mode 100644 platform/linux-dpdk/odp_init.c
> >  create mode 100644 platform/linux-dpdk/odp_linux.c
> >  create mode 100644 platform/linux-dpdk/odp_packet.c
> >  create mode 100644 platform/linux-dpdk/odp_packet_dpdk.c
> >  create mode 100644 platform/linux-dpdk/odp_packet_io.c
> >  create mode 100644 platform/linux-dpdk/odp_queue.c
> >
> > diff --git a/configure.ac b/configure.ac
> > index 873ea9e..3d8481f 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -51,6 +51,7 @@ AC_ARG_WITH([platform],
> >
> >  AM_CONDITIONAL([ODP_PLATFORM_GENERIC], [test "x$with_platform" =
> xlinux-generic])
> >  AM_CONDITIONAL([ODP_PLATFORM_KEYSTONE2], [test "x$with_platform" =
> xlinux-keystone2])
> > +AM_CONDITIONAL([ODP_PLATFORM_DPDK], [test "x$with_platform" =
> xlinux-dpdk])
> >
> >  AC_SUBST([with_platform])
> >
> > @@ -111,6 +112,7 @@ AC_CONFIG_FILES([Makefile
> >                platform/Makefile
> >                platform/linux-generic/Makefile
> >                platform/linux-keystone2/Makefile
> > +              platform/linux-dpdk/Makefile
> >                test/Makefile
> >                test/api_test/Makefile
> >                test/example/Makefile
> > diff --git a/platform/linux-dpdk/Makefile.am
> b/platform/linux-dpdk/Makefile.am
> > new file mode 100644
> > index 0000000..067c0bb
> > --- /dev/null
> > +++ b/platform/linux-dpdk/Makefile.am
> > @@ -0,0 +1,100 @@
> > +include $(top_srcdir)/Makefile.inc
> > +LIB   = $(top_builddir)/lib
> > +
> > +dist_pkgdata_DATA = $(LIB)/libodp.la
> > +
> > +pkgconfigdir = pkgconfig
> > +nodist_pkgconfig_DATA = $(top_builddir)/pkgconfig/libodp.pc
> > +
> > +.PHONY: pkgconfig/libodp.pc
> > +
> > +RTE_SDK    ?= $(top_srcdir)/../dpdk
> > +RTE_OUTPUT ?= $(RTE_SDK)/build
> > +RTE_LIB    ?= $(RTE_OUTPUT)/lib
> > +
> > +PLAT_CFLAGS  = -include $(RTE_OUTPUT)/include/rte_config.h
>
> why do you need to specify this like that?
>
> > +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include
> > +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch
> > +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env
>
> Remove this... too hardcoded... do as ks2
>
> Something like this:
> $ ./configure --with-platform=linux-dpdk
> LDFLAGS=-L/home/anders/src/dpdk/build/lib CFLAGS="-include
> /home/anders/src/for_dpdk/build/include/rte_config.h
> -I/home/anders/src/for_dpdk/build/include
> -I/home/anders/src/for_dpdk/build/include/arch
> -I/home/anders/src/for_dpdk/build/include/exec-env"
>
> I used build instead of my_sdk_build_dir that was stated in the README
>
>
> $ gitt df
> diff --git a/platform/linux-dpdk/Makefile.am
> b/platform/linux-dpdk/Makefile.am
> index 067c0bb..f9f31c6 100644
> --- a/platform/linux-dpdk/Makefile.am
> +++ b/platform/linux-dpdk/Makefile.am
> @@ -8,15 +8,7 @@ nodist_pkgconfig_DATA =
> $(top_builddir)/pkgconfig/libodp.pc
>
>  .PHONY: pkgconfig/libodp.pc
>
> -RTE_SDK    ?= $(top_srcdir)/../dpdk
> -RTE_OUTPUT ?= $(RTE_SDK)/build
> -RTE_LIB    ?= $(RTE_OUTPUT)/lib
> -
> -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
> +PLAT_CFLAGS = -msse4.2
>
>  AM_CFLAGS +=  $(PLAT_CFLAGS)
>  AM_CFLAGS +=  -I$(srcdir)/include
> @@ -25,7 +17,6 @@ AM_CFLAGS +=
>  -I$(top_srcdir)/platform/linux-generic/include
>  AM_CFLAGS +=  -I$(top_srcdir)/platform/linux-generic/include/api
>  AM_CFLAGS +=  -I$(top_srcdir)/include
>
> -AM_LDFLAGS += -L$(RTE_LIB)
>  VPATH = $(srcdir) $(builddir)
>  if ODP_PLATFORM_DPDK
>  lib_LTLIBRARIES = $(LIB)/libodp.la


Removed all these hardcoding and added commandline parameter similar to ks2
as per your suggestion.


>
>
>
> > +PLAT_CFLAGS += -msse4.2
> > +
> > +AM_CFLAGS +=  $(PLAT_CFLAGS)
> > +AM_CFLAGS +=  -I$(srcdir)/include
> > +AM_CFLAGS +=  -I$(srcdir)/include/api
> > +AM_CFLAGS +=  -I$(top_srcdir)/platform/linux-generic/include
> > +AM_CFLAGS +=  -I$(top_srcdir)/platform/linux-generic/include/api
> > +AM_CFLAGS +=  -I$(top_srcdir)/include
> > +
> > +AM_LDFLAGS += -L$(RTE_LIB)
> > +VPATH = $(srcdir) $(builddir)
> > +if ODP_PLATFORM_DPDK
> > +lib_LTLIBRARIES = $(LIB)/libodp.la
> > +DPDK_LIBS="-lintel_dpdk -ldl"
> > +LIBS += $(DPDK_LIBS)
> > +
> > +include_HEADERS = \
> > +
> $(top_srcdir)/platform/linux-dpdk/include/api/odp_buffer.h \
> > +               $(top_srcdir)/include/odp.h \
> > +               $(top_srcdir)/include/odp_align.h \
> > +               $(top_srcdir)/include/odp_atomic.h \
> > +               $(top_srcdir)/include/odp_barrier.h \
> > +               $(top_srcdir)/include/odp_buffer_pool.h \
> > +               $(top_srcdir)/include/odp_byteorder.h \
> > +               $(top_srcdir)/include/odp_compiler.h \
> > +               $(top_srcdir)/include/odp_config.h \
> > +               $(top_srcdir)/include/odp_coremask.h \
> > +               $(top_srcdir)/include/odp_debug.h \
> > +               $(top_srcdir)/include/odp_hints.h \
> > +               $(top_srcdir)/include/odp_init.h \
> > +               $(top_srcdir)/include/odp_packet_flags.h \
> > +               $(top_srcdir)/include/odp_packet.h \
> > +               $(top_srcdir)/include/odp_packet_io.h \
> > +               $(top_srcdir)/include/odp_queue.h \
> > +               $(top_srcdir)/include/odp_rwlock.h \
> > +               $(top_srcdir)/include/odp_schedule.h \
> > +               $(top_srcdir)/include/odp_shared_memory.h \
> > +               $(top_srcdir)/include/odp_spinlock.h \
> > +               $(top_srcdir)/include/odp_std_types.h \
> > +               $(top_srcdir)/include/odp_sync.h \
> > +               $(top_srcdir)/include/odp_system_info.h \
> > +               $(top_srcdir)/include/odp_thread.h \
> > +               $(top_srcdir)/include/odp_ticketlock.h \
> > +               $(top_srcdir)/include/odp_time.h \
> > +               $(top_srcdir)/include/odp_timer.h \
> > +               $(top_srcdir)/include/odp_version.h
> > +
> > +subdirheadersdir = $(includedir)/helper
> > +subdirheaders_HEADERS = \
> > +                     $(top_srcdir)/include/helper/odp_chksum.h \
> > +                     $(top_srcdir)/include/helper/odp_eth.h \
> > +                     $(top_srcdir)/include/helper/odp_ip.h \
> > +                     $(top_srcdir)/include/helper/odp_linux.h \
> > +                     $(top_srcdir)/include/helper/odp_packet_helper.h \
> > +                     $(top_srcdir)/include/helper/odp_ring.h \
> > +                     $(top_srcdir)/include/helper/odp_udp.h
> > +
> > +__LIB__libodp_la_SOURCES = \
> > +                        ../linux-generic/odp_barrier.c \
> > +                        odp_buffer.c \
> > +                        odp_buffer_pool.c \
> > +                        ../linux-generic/odp_coremask.c \
> > +                        odp_init.c \
> > +                        odp_linux.c \
> > +                        odp_packet.c \
> > +                        odp_packet_dpdk.c \
> > +                        ../linux-generic/odp_packet_flags.c \
> > +                        odp_packet_io.c \
> > +                        ../linux-generic/odp_packet_socket.c \
> > +                        odp_queue.c \
> > +                        ../linux-generic/odp_ring.c \
> > +                        ../linux-generic/odp_rwlock.c \
> > +                        ../linux-generic/odp_schedule.c \
> > +                        ../linux-generic/odp_shared_memory.c \
> > +                        ../linux-generic/odp_spinlock.c \
> > +                        ../linux-generic/odp_system_info.c \
> > +                        ../linux-generic/odp_thread.c \
> > +                        ../linux-generic/odp_ticketlock.c \
> > +                        ../linux-generic/odp_time.c \
> > +                        ../linux-generic/odp_timer.c
> > +
> > +endif
> > diff --git a/platform/linux-dpdk/README b/platform/linux-dpdk/README
> > new file mode 100644
> > index 0000000..69116a7
> > --- /dev/null
> > +++ b/platform/linux-dpdk/README
> > @@ -0,0 +1,70 @@
> > +ODP-DPDK:
> > +---------
> > +     This effort is to port ODP on top of DPDK and use dpdk as the
> > +accelerator for all intel NIC's. Pre-requisite is DPDK should be cloned
> and
> > +compiled.
> > +
> > +# To Clone DPDK
> > +$ git clone http://92.243.14.124/git/dpdk ./dpdk
> > +# Ensure that dpdk is present at the same directory level as odp, that
> is, ./odp and ./dpdk
> > +# we support only 1.6.0r2 of dpdk for now
> > +$ git tag -l -- will list all the tags available
> > +$ git checkout tags/v1.6.0r2
>
> Oh right I wasn't able to build dpdk I'm using Ubuntu-14.04 with kernel
> 3.13.0-30-generic
>
> I had to do this change to dpdk:
>
>  $ git df
> diff --git a/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h
> b/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h
> index 19df483..78a794a 100644
> --- a/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h
> +++ b/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h
> @@ -3845,11 +3845,6 @@ static inline struct sk_buff
> *__kc__vlan_hwaccel_put_tag(struct sk_buff *skb,
>  #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) )
>  #ifdef NETIF_F_RXHASH
>  #define PKT_HASH_TYPE_L3 0
> -static inline void
> -skb_set_hash(struct sk_buff *skb, __u32 hash, __always_unused int type)
> -{
> -       skb->rxhash = hash;
> -}
>  #endif /* NETIF_F_RXHASH */
>  #endif /* < 3.14.0 */
>
> This is something that has to be fixed by dpdk. Looks like someone has
already raised the issue,

permalink.gmane.org/gmane.comp.networking.dpdk.devel/4041

It works fine with kernel version 3.13.0.-29-generic,

$ uname -a
Linux apslabuser-PowerEdge-T610 3.13.0-29-generic #53-Ubuntu SMP Wed Jun 4
21:00:20 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux



> > +
> > +$ cd ./dpdk
> > +# Only for the first time
> > +$ make config T=x86_64-default-linuxapp-gcc O=my_sdk_build_dir
>
> The O= you should be able to set that to whatever you want right?
>
> s|my_sdk_build_dir|<abs/path/to/dpdk/build/dir>|
>

> > +set CONFIG_RTE_BUILD_COMBINE_LIBS=y in my_sdk_build_dir/.config
>
> Maybe change s|set|# set|
>
> > +
> > +Note: If not-intel SFP's are used in NIC, then go to
> my_sdk_build_dir/.config and set
> CONFIG_RTE_LIBRTE_IXGBE_ALLOW_UNSUPPORTED_SFP=y
> > +
> > +$ cd my_sdk_build_dir/
>
> s|my_sdk_build_dir|<abs/path/to/dpdk/build/dir>|
>

Modified and sent along as v5.


> > +$ make clean; make
> > +
> > +# To reserve huge pages which is needed for dpdk execute following
> command
> > +$ echo 1024 >
> /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
> > +# If you are running on a multi-node machine then, hugepages should be
> reserved on each node
> > +$ echo 1024 >
> /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
> > +
> > +$ sudo mkdir /mnt/huge
> > +$ sudo mount -t hugetlbfs nodev /mnt/huge
> > +# To load uio driver
> > +$ sudo /sbin/modprobe uio
> > +$ ulimit -Sn 2048
> > +
> > +# sudo insmod igb_uio.ko
> > +$ cd ./dpdk
> > +$ insmod ./build/build/lib/librte_eal/linuxapp/igb_uio/igb_uio.ko
> > +
> > +$ rmmod ixgbe
> > +$ modprobe ixgbe
> > +# If the SFP's used are non-intel, then
> > +$ modprobe ixgbe allow_unsupported_sfp=1
> > +
> > +$ cd ./dpdk
> > +$ ./tools/igb_uio_bind.py --status
> > +
> > +Now you should look for pci id listed and give it in the following
> command in
> > +place of 42:00.0
> > +
> > +# To give the interfaces to dpdk, use following command
> > +$ sudo ./tools/igb_uio_bind.py --bind=igb_uio 42:00.0
> > +$ sudo ./tools/igb_uio_bind.py --bind=igb_uio 42:00.1
> > +# To restore it back to kernel, use following command
> > +$ sudo ./tools/igb_uio_bind.py --bind=ixgbe 42:00.0
> > +$ sudo ./tools/igb_uio_bind.py --bind=ixgbe 42:00.1
> > +
> > +# To compile ODP with linux-dpdk
> > +$ ./bootstrap
> > +$ ./configure --with-platform=linux-dpdk
>
> And maybe add to the ./configure command:
> LDFLAGS=-L<dpdk-build-dir>/lib CFLAGS="-include
> <dpdk-build-dir>/include/rte_config.h
> -I<dpdk-build-dir>/include
> -I<dpdk-build-dir>/include/arch
> -I<dpdk-build-dir>/include/exec-env"
>

Done in v5


>
> Cheers,
> Anders
>
> > +$ make clean
> > +$ make
> > +
> > +# Commands to test
> > +l2fwding app - ./test/l2fwd/odp_l2fwd -i 0,1 -t 5 -m 0 -c 2
> > +loopback app - ./test/packet/odp_pktio -i 0,1 -t 5 -m 0 -c 2
> > +
> > +     -i 0,1 - interface number
> > +     -t 5   - dpdk type
> > +     -m 0   - burst mode
> > +     -c 2   - number of cpus
> > 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..9ea1ed8
> > --- /dev/null
> > +++ b/platform/linux-dpdk/include/api/odp_buffer.h
> > @@ -0,0 +1,94 @@
> > +/* 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_ANY       0  /**< Buffer that can hold any other
> > +                                       buffer type */
> > +#define ODP_BUFFER_TYPE_RAW       1  /**< Raw buffer, no additional
> metadata */
> > +#define ODP_BUFFER_TYPE_PACKET    2  /**< Packet buffer */
> > +#define ODP_BUFFER_TYPE_TIMEOUT   3  /**< Timeout buffer */
> > +
> > +/**
> > + * 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..f87ec80
> > --- /dev/null
> > +++ b/platform/linux-dpdk/include/odp_buffer_internal.h
> > @@ -0,0 +1,72 @@
> > +/* 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..bcbe9e8
> > --- /dev/null
> > +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
> > @@ -0,0 +1,87 @@
> > +/* 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..0f798c1
> > --- /dev/null
> > +++ b/platform/linux-dpdk/include/odp_packet_internal.h
> > @@ -0,0 +1,139 @@
> > +/* 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..08abea7
> > --- /dev/null
> > +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
> > @@ -0,0 +1,51 @@
> > +/* 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/odp_buffer.c
> b/platform/linux-dpdk/odp_buffer.c
> > new file mode 100644
> > index 0000000..e2f8942
> > --- /dev/null
> > +++ b/platform/linux-dpdk/odp_buffer.c
> > @@ -0,0 +1,90 @@
> > +/* 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_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/odp_buffer_pool.c
> b/platform/linux-dpdk/odp_buffer_pool.c
> > new file mode 100644
> > index 0000000..de90275
> > --- /dev/null
> > +++ b/platform/linux-dpdk/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/odp_init.c
> b/platform/linux-dpdk/odp_init.c
> > new file mode 100644
> > index 0000000..ecc2066
> > --- /dev/null
> > +++ b/platform/linux-dpdk/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/odp_linux.c
> b/platform/linux-dpdk/odp_linux.c
> > new file mode 100644
> > index 0000000..067bd99
> > --- /dev/null
> > +++ b/platform/linux-dpdk/odp_linux.c
> > @@ -0,0 +1,96 @@
> > +/* Copyright (c) 2013, Linaro Limited
> > + * All rights reserved.
> > + *
> > + * SPDX-License-Identifier:     BSD-3-Clause
> > + */
> > +
> > +#ifndef _GNU_SOURCE
> > +#define _GNU_SOURCE
> > +#endif
> > +#include <sched.h>
> > +
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <stdio.h>
> > +#include <assert.h>
> > +
> > +#include <helper/odp_linux.h>
> > +#include <odp_internal.h>
> > +#include <odp_thread.h>
> > +#include <odp_init.h>
> > +#include <odp_system_info.h>
> > +
> > +#include <rte_lcore.h>
> > +
> > +typedef struct {
> > +     int thr_id;
> > +     void *(*start_routine) (void *);
> > +     void *arg;
> > +
> > +} odp_start_args_t;
> > +
> > +
> > +static void *odp_run_start_routine(void *arg)
> > +{
> > +     odp_start_args_t *start_args = arg;
> > +
> > +     /* ODP thread local init */
> > +     odp_init_local(start_args->thr_id);
> > +
> > +     return start_args->start_routine(start_args->arg);
> > +}
> > +
> > +
> > +void odp_linux_pthread_create(odp_linux_pthread_t *thread_tbl, int num,
> > +             int first_core, void *(*start_routine) (void *), void *arg)
> > +{
> > +     int i;
> > +     cpu_set_t cpu_set;
> > +     odp_start_args_t *start_args;
> > +     int core_count;
> > +     int cpu;
> > +
> > +     (void) cpu_set;
> > +     (void) thread_tbl;
> > +
> > +     core_count = odp_sys_core_count();
> > +
> > +     assert((first_core >= 0) && (first_core < core_count));
> > +     assert((num >= 0) && (num <= core_count));
> > +
> > +     for (i = 0; i < num; i++) {
> > +             cpu = (first_core + i) % core_count;
> > +
> > +             start_args = malloc(sizeof(odp_start_args_t));
> > +             memset(start_args, 0, sizeof(odp_start_args_t));
> > +             start_args->start_routine = start_routine;
> > +             start_args->arg           = arg;
> > +
> > +             odp_thread_create(cpu);
> > +             start_args->thr_id = cpu;
> > +             /* If not master core */
> > +             if (cpu != 0) {
> > +                     rte_eal_remote_launch(
> > +                             (int(*)(void *))odp_run_start_routine,
> > +                             start_args, cpu);
> > +             } else {
> > +                     lcore_config[cpu].ret = (int)(uint64_t)
> > +                             odp_run_start_routine(start_args);
> > +                     lcore_config[cpu].state = FINISHED;
> > +             }
> > +     }
> > +}
> > +
> > +
> > +void odp_linux_pthread_join(odp_linux_pthread_t *thread_tbl, int num)
> > +{
> > +     uint32_t lcore_id;
> > +
> > +     (void) thread_tbl;
> > +     (void) num;
> > +
> > +     RTE_LCORE_FOREACH_SLAVE(lcore_id) {
> > +     if (rte_eal_wait_lcore(lcore_id) < 0)
> > +             return;
> > +     }
> > +}
> > diff --git a/platform/linux-dpdk/odp_packet.c
> b/platform/linux-dpdk/odp_packet.c
> > new file mode 100644
> > index 0000000..c34e626
> > --- /dev/null
> > +++ b/platform/linux-dpdk/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/odp_packet_dpdk.c
> b/platform/linux-dpdk/odp_packet_dpdk.c
> > new file mode 100644
> > index 0000000..31bfa30
> > --- /dev/null
> > +++ b/platform/linux-dpdk/odp_packet_dpdk.c
> > @@ -0,0 +1,189 @@
> > +/* 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 16
> > +#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("dpdk netdev: %s\n", netdev);
> > +     printf("dpdk pool: %lx\n", pool);
> > +
> > +     portid = atoi(netdev);
> > +     pkt_dpdk->portid = portid;
> > +     pkt_dpdk->queueid = queueid;
> > +     pkt_dpdk->pool = pool;
> > +     printf("dpdk 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)
> > +{
> > +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t nb_rx, i = 0;
> > +
> > +     memset(pkts_burst, 0 , sizeof(pkts_burst));
> > +     nb_rx = rte_eth_rx_burst((uint8_t)pkt_dpdk->portid,
> > +                              (uint16_t)pkt_dpdk->queueid,
> > +                              (struct rte_mbuf **)pkts_burst,
> (uint16_t)len);
> > +     for (i = 0; i < nb_rx; i++)
> > +             pkt_table[i] = (odp_packet_t)pkts_burst[i];
> > +     return nb_rx;
> > +}
> > +
> > +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
> > +             unsigned len)
> > +{
> > +     struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
> > +     uint16_t i;
> > +
> > +     for (i = 0; i < len; i++)
> > +             pkts_burst[i] = (struct rte_mbuf *)pkt_table[i];
> > +     return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid,
> > +                             (uint16_t)pkt_dpdk->queueid,
> > +                             (struct rte_mbuf **)pkts_burst,
> (uint16_t)len);
> > +}
> > diff --git a/platform/linux-dpdk/odp_packet_io.c
> b/platform/linux-dpdk/odp_packet_io.c
> > new file mode 100644
> > index 0000000..abea0ec
> > --- /dev/null
> > +++ b/platform/linux-dpdk/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/odp_queue.c
> b/platform/linux-dpdk/odp_queue.c
> > new file mode 100644
> > index 0000000..554b8ea
> > --- /dev/null
> > +++ b/platform/linux-dpdk/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.8.1.2
> >
> >
> > _______________________________________________
> > lng-odp mailing list
> > lng-odp@lists.linaro.org
> > http://lists.linaro.org/mailman/listinfo/lng-odp
>
> --
> Anders Roxell
> anders.roxell@linaro.org
> M: +46 709 71 42 85 | IRC: roxell
>
diff mbox

Patch

diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am
index 067c0bb..f9f31c6 100644
--- a/platform/linux-dpdk/Makefile.am
+++ b/platform/linux-dpdk/Makefile.am
@@ -8,15 +8,7 @@  nodist_pkgconfig_DATA = $(top_builddir)/pkgconfig/libodp.pc
 
 .PHONY: pkgconfig/libodp.pc
 
-RTE_SDK    ?= $(top_srcdir)/../dpdk
-RTE_OUTPUT ?= $(RTE_SDK)/build
-RTE_LIB    ?= $(RTE_OUTPUT)/lib
-
-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
+PLAT_CFLAGS = -msse4.2
 
 AM_CFLAGS +=  $(PLAT_CFLAGS)
 AM_CFLAGS +=  -I$(srcdir)/include
@@ -25,7 +17,6 @@  AM_CFLAGS +=  -I$(top_srcdir)/platform/linux-generic/include
 AM_CFLAGS +=  -I$(top_srcdir)/platform/linux-generic/include/api
 AM_CFLAGS +=  -I$(top_srcdir)/include
 
-AM_LDFLAGS += -L$(RTE_LIB)
 VPATH = $(srcdir) $(builddir)
 if ODP_PLATFORM_DPDK
 lib_LTLIBRARIES = $(LIB)/libodp.la


> +PLAT_CFLAGS += -msse4.2
> +
> +AM_CFLAGS +=  $(PLAT_CFLAGS)
> +AM_CFLAGS +=  -I$(srcdir)/include
> +AM_CFLAGS +=  -I$(srcdir)/include/api
> +AM_CFLAGS +=  -I$(top_srcdir)/platform/linux-generic/include
> +AM_CFLAGS +=  -I$(top_srcdir)/platform/linux-generic/include/api
> +AM_CFLAGS +=  -I$(top_srcdir)/include
> +
> +AM_LDFLAGS += -L$(RTE_LIB)
> +VPATH = $(srcdir) $(builddir)
> +if ODP_PLATFORM_DPDK
> +lib_LTLIBRARIES = $(LIB)/libodp.la
> +DPDK_LIBS="-lintel_dpdk -ldl"
> +LIBS += $(DPDK_LIBS)
> +
> +include_HEADERS = \
> +		  $(top_srcdir)/platform/linux-dpdk/include/api/odp_buffer.h \
> +		  $(top_srcdir)/include/odp.h \
> +		  $(top_srcdir)/include/odp_align.h \
> +		  $(top_srcdir)/include/odp_atomic.h \
> +		  $(top_srcdir)/include/odp_barrier.h \
> +		  $(top_srcdir)/include/odp_buffer_pool.h \
> +		  $(top_srcdir)/include/odp_byteorder.h \
> +		  $(top_srcdir)/include/odp_compiler.h \
> +		  $(top_srcdir)/include/odp_config.h \
> +		  $(top_srcdir)/include/odp_coremask.h \
> +		  $(top_srcdir)/include/odp_debug.h \
> +		  $(top_srcdir)/include/odp_hints.h \
> +		  $(top_srcdir)/include/odp_init.h \
> +		  $(top_srcdir)/include/odp_packet_flags.h \
> +		  $(top_srcdir)/include/odp_packet.h \
> +		  $(top_srcdir)/include/odp_packet_io.h \
> +		  $(top_srcdir)/include/odp_queue.h \
> +		  $(top_srcdir)/include/odp_rwlock.h \
> +		  $(top_srcdir)/include/odp_schedule.h \
> +		  $(top_srcdir)/include/odp_shared_memory.h \
> +		  $(top_srcdir)/include/odp_spinlock.h \
> +		  $(top_srcdir)/include/odp_std_types.h \
> +		  $(top_srcdir)/include/odp_sync.h \
> +		  $(top_srcdir)/include/odp_system_info.h \
> +		  $(top_srcdir)/include/odp_thread.h \
> +		  $(top_srcdir)/include/odp_ticketlock.h \
> +		  $(top_srcdir)/include/odp_time.h \
> +		  $(top_srcdir)/include/odp_timer.h \
> +		  $(top_srcdir)/include/odp_version.h
> +
> +subdirheadersdir = $(includedir)/helper
> +subdirheaders_HEADERS = \
> +			$(top_srcdir)/include/helper/odp_chksum.h \
> +			$(top_srcdir)/include/helper/odp_eth.h \
> +			$(top_srcdir)/include/helper/odp_ip.h \
> +			$(top_srcdir)/include/helper/odp_linux.h \
> +			$(top_srcdir)/include/helper/odp_packet_helper.h \
> +			$(top_srcdir)/include/helper/odp_ring.h \
> +			$(top_srcdir)/include/helper/odp_udp.h
> +
> +__LIB__libodp_la_SOURCES = \
> +			   ../linux-generic/odp_barrier.c \
> +			   odp_buffer.c \
> +			   odp_buffer_pool.c \
> +			   ../linux-generic/odp_coremask.c \
> +			   odp_init.c \
> +			   odp_linux.c \
> +			   odp_packet.c \
> +			   odp_packet_dpdk.c \
> +			   ../linux-generic/odp_packet_flags.c \
> +			   odp_packet_io.c \
> +			   ../linux-generic/odp_packet_socket.c \
> +			   odp_queue.c \
> +			   ../linux-generic/odp_ring.c \
> +			   ../linux-generic/odp_rwlock.c \
> +			   ../linux-generic/odp_schedule.c \
> +			   ../linux-generic/odp_shared_memory.c \
> +			   ../linux-generic/odp_spinlock.c \
> +			   ../linux-generic/odp_system_info.c \
> +			   ../linux-generic/odp_thread.c \
> +			   ../linux-generic/odp_ticketlock.c \
> +			   ../linux-generic/odp_time.c \
> +			   ../linux-generic/odp_timer.c
> +
> +endif
> diff --git a/platform/linux-dpdk/README b/platform/linux-dpdk/README
> new file mode 100644
> index 0000000..69116a7
> --- /dev/null
> +++ b/platform/linux-dpdk/README
> @@ -0,0 +1,70 @@
> +ODP-DPDK:
> +---------
> +	This effort is to port ODP on top of DPDK and use dpdk as the
> +accelerator for all intel NIC's. Pre-requisite is DPDK should be cloned and
> +compiled.
> +
> +# To Clone DPDK
> +$ git clone http://92.243.14.124/git/dpdk ./dpdk
> +# Ensure that dpdk is present at the same directory level as odp, that is, ./odp and ./dpdk
> +# we support only 1.6.0r2 of dpdk for now
> +$ git tag -l -- will list all the tags available
> +$ git checkout tags/v1.6.0r2

Oh right I wasn't able to build dpdk I'm using Ubuntu-14.04 with kernel
3.13.0-30-generic

I had to do this change to dpdk:

 $ git df
diff --git a/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h b/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h
index 19df483..78a794a 100644
--- a/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h
+++ b/lib/librte_eal/linuxapp/kni/ethtool/igb/kcompat.h
@@ -3845,11 +3845,6 @@  static inline struct sk_buff *__kc__vlan_hwaccel_put_tag(struct sk_buff *skb,
 #if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) )
 #ifdef NETIF_F_RXHASH
 #define PKT_HASH_TYPE_L3 0
-static inline void
-skb_set_hash(struct sk_buff *skb, __u32 hash, __always_unused int type)
-{
-       skb->rxhash = hash;
-}
 #endif /* NETIF_F_RXHASH */
 #endif /* < 3.14.0 */