Message ID | 1405623827-29896-1-git-send-email-venkatesh.vivekanandan@linaro.org |
---|---|
State | New |
Headers | show |
On 17 July 2014 15:03, <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 | 76 ++++ > 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 | 419 > ++++++++++++++++++++ > platform/linux-dpdk/odp_queue.c | 435 > +++++++++++++++++++++ > 20 files changed, 2955 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..8f5b94b > --- /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 > +#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 > + > +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..3578512 > --- /dev/null > +++ b/platform/linux-dpdk/README > @@ -0,0 +1,76 @@ > +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-dir> > +# 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 > + > +$ cd <dpdk-dir> > + > +# Only for the first time > +$ make config T=x86_64-default-linuxapp-gcc > +# above command will generate build directory as ./build by default in > +# <dpdk-dir> which can be overridden by specifying O=my_build_dir option > as > +$ make config T=x86_64-default-linuxapp-gcc O=my_sdk_build_dir > For the above there are two make commands listed, it is not clear which is needed. I assumed that that iit is the first the one. > +# set CONFIG_RTE_BUILD_COMBINE_LIBS=y in <dpdk-build-dir>/.config > This is commented out but I think it is a required step, so maybe it should have a comment say "and now edit this file" > + > +Note: If non-intel SFP's are used in NIC, then go to > <dpdk-build-dir>/.config > +and set CONFIG_RTE_LIBRTE_IXGBE_ALLOW_UNSUPPORTED_SFP=y > + > +$ cd <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 > I had to use sudo for this sudo sh -c '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 > Should we spell out doing "ls /sys/devices/system/node" to discover how many nodes you have ? > + > +$ sudo mkdir /mnt/huge > +$ sudo mount -t hugetlbfs nodev /mnt/huge > +# To load uio driver > +$ sudo /sbin/modprobe uio > +$ ulimit -Sn 2048 > + > +$ cd <dpdk-dir> > +$ sudo insmod ./build/build/lib/librte_eal/linuxapp/igb_uio/igb_uio.ko > + > +$ rmmod ixgbe > should this be sudo ? > +$ modprobe ixgbe > should this be sudo > +# If the SFP's used are non-intel, then > +$ modprobe ixgbe allow_unsupported_sfp=1 > should this be sudo > + > +$ cd <dpdk-dir> > +$ ./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 > should there be an example of the output like below but for a real device ? > Network devices using IGB_UIO driver ==================================== <none> Network devices using kernel driver =================================== 0000:06:00.0 'NetXtreme BCM5761 Gigabit Ethernet PCIe' if=eth0 drv=tg3 unused=<none> *Active* Other network devices ===================== <none> > +# 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 > Should this list cd to your ODP directory here because the previous instructions are that detailed? > +$ ./bootstrap > +$ ./configure --with-platform=linux-dpdk 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" > Can we change all the <dpdk-build-dir> to be using the defaults - in this case basically ../dpdk so that it can be blindly cut and paste - OR maybe better in the instructions set an export at the beginning that points at DPDK and use $dpdk-build-dir. Alao a not that you must use full paths not relative ? > +# For example > +$ ./configure --with-platform=linux-dpdk LDFLAGS=-L/root/dpdk/build/lib > CFLAGS="-include /root/dpdk/build/include/rte_config.h > -I/root/dpdk/build/include -I/root/dpdk/build/include/arch > -I/root/dpdk/build/include/exec-env" > +$ make clean > +$ make > + > +# Commands to test > +l2fwding app - ./test/l2fwd/odp_l2fwd -i 0,1 -m 0 -c 2 > +loopback app - ./test/packet/odp_pktio -i 0,1 -m 0 -c 2 > + > + -i 0,1 - interface number > + -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 *)ð->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, ð_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..d8d127f > --- /dev/null > +++ b/platform/linux-dpdk/odp_packet_io.c > @@ -0,0 +1,419 @@ > +/* 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; > + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); > + /* 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; > + } > + > + ODP_DBG("Allocating dpdk pktio\n"); > + > + 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); > + > + 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; > + } > + > + 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)) { > + res = close_pkt_dpdk(&entry->s.pkt_dpdk); > + 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); > + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, len); > + 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); > + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, > + pkt_table, len); > + 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 >
Why can't we remove DPDK build method from odp-dpdk readme, with one note that user should aware of dpdk env/build details. I did dpdk setup on non-ubuntu distro (centos) and it asks for little different package dependency for me. Dependency may vary from one distro to another (a little though). On 18 July 2014 03:11, Mike Holmes <mike.holmes@linaro.org> wrote: > > > > On 17 July 2014 15:03, <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 | 76 ++++ >> 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 | 419 >> ++++++++++++++++++++ >> platform/linux-dpdk/odp_queue.c | 435 >> +++++++++++++++++++++ >> 20 files changed, 2955 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..8f5b94b >> --- /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 >> +#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 >> + >> +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..3578512 >> --- /dev/null >> +++ b/platform/linux-dpdk/README >> @@ -0,0 +1,76 @@ >> +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-dir> >> +# 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 >> + >> +$ cd <dpdk-dir> >> + >> +# Only for the first time >> +$ make config T=x86_64-default-linuxapp-gcc >> +# above command will generate build directory as ./build by default in >> +# <dpdk-dir> which can be overridden by specifying O=my_build_dir option >> as >> +$ make config T=x86_64-default-linuxapp-gcc O=my_sdk_build_dir > > For the above there are two make commands listed, it is not clear which is > needed. > I assumed that that iit is the first the one. > >> >> +# set CONFIG_RTE_BUILD_COMBINE_LIBS=y in <dpdk-build-dir>/.config > > This is commented out but I think it is a required step, so maybe it should > have > a comment say "and now edit this file" >> >> + >> +Note: If non-intel SFP's are used in NIC, then go to >> <dpdk-build-dir>/.config >> +and set CONFIG_RTE_LIBRTE_IXGBE_ALLOW_UNSUPPORTED_SFP=y >> + >> +$ cd <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 > > I had to use sudo for this > sudo sh -c '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 > > Should we spell out doing "ls /sys/devices/system/node" to discover how > many nodes you have ? >> >> + >> +$ sudo mkdir /mnt/huge >> +$ sudo mount -t hugetlbfs nodev /mnt/huge >> +# To load uio driver >> +$ sudo /sbin/modprobe uio >> +$ ulimit -Sn 2048 >> + >> +$ cd <dpdk-dir> >> +$ sudo insmod ./build/build/lib/librte_eal/linuxapp/igb_uio/igb_uio.ko >> + >> +$ rmmod ixgbe > > should this be sudo ? >> >> +$ modprobe ixgbe > > should this be sudo >> >> +# If the SFP's used are non-intel, then >> +$ modprobe ixgbe allow_unsupported_sfp=1 > > should this be sudo >> >> + >> +$ cd <dpdk-dir> >> +$ ./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 >> should there be an example of the output like below but for a real device >> ? > > > Network devices using IGB_UIO driver > ==================================== > <none> > > Network devices using kernel driver > =================================== > 0000:06:00.0 'NetXtreme BCM5761 Gigabit Ethernet PCIe' if=eth0 drv=tg3 > unused=<none> *Active* > > Other network devices > ===================== > <none> > > >> >> +# 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 > > Should this list cd to your ODP directory here because the previous > instructions are that detailed? >> >> +$ ./bootstrap >> +$ ./configure --with-platform=linux-dpdk 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" > > Can we change all the <dpdk-build-dir> to be using the defaults - in this > case basically ../dpdk so that it can be blindly cut and paste - OR maybe > better in the instructions set an export at the beginning that points at > DPDK and use $dpdk-build-dir. Alao a not that you must use full paths not > relative ? >> >> +# For example >> +$ ./configure --with-platform=linux-dpdk LDFLAGS=-L/root/dpdk/build/lib >> CFLAGS="-include /root/dpdk/build/include/rte_config.h >> -I/root/dpdk/build/include -I/root/dpdk/build/include/arch >> -I/root/dpdk/build/include/exec-env" >> +$ make clean >> +$ make >> + >> +# Commands to test >> +l2fwding app - ./test/l2fwd/odp_l2fwd -i 0,1 -m 0 -c 2 >> +loopback app - ./test/packet/odp_pktio -i 0,1 -m 0 -c 2 >> + >> + -i 0,1 - interface number >> + -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 *)ð->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, ð_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..d8d127f >> --- /dev/null >> +++ b/platform/linux-dpdk/odp_packet_io.c >> @@ -0,0 +1,419 @@ >> +/* 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; >> + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); >> + /* 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; >> + } >> + >> + ODP_DBG("Allocating dpdk pktio\n"); >> + >> + 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); >> + >> + 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; >> + } >> + >> + 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)) { >> + res = close_pkt_dpdk(&entry->s.pkt_dpdk); >> + 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); >> + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, len); >> + 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); >> + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, >> + pkt_table, len); >> + 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 > > > > > -- > Mike Holmes > Linaro Technical Manager / Lead > LNG - ODP > > _______________________________________________ > lng-odp mailing list > lng-odp@lists.linaro.org > http://lists.linaro.org/mailman/listinfo/lng-odp >
On 18 July 2014 03:11, Mike Holmes <mike.holmes@linaro.org> wrote: > > > > On 17 July 2014 15:03, <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 | 76 ++++ >> 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 | 419 >> ++++++++++++++++++++ >> platform/linux-dpdk/odp_queue.c | 435 >> +++++++++++++++++++++ >> 20 files changed, 2955 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..8f5b94b >> --- /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 >> +#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 >> + >> +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..3578512 >> --- /dev/null >> +++ b/platform/linux-dpdk/README >> @@ -0,0 +1,76 @@ >> +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-dir> >> +# 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 >> + >> +$ cd <dpdk-dir> >> + >> +# Only for the first time >> +$ make config T=x86_64-default-linuxapp-gcc >> +# above command will generate build directory as ./build by default in >> +# <dpdk-dir> which can be overridden by specifying O=my_build_dir option >> as >> +$ make config T=x86_64-default-linuxapp-gcc O=my_sdk_build_dir >> > For the above there are two make commands listed, it is not clear which is > needed. > I assumed that that iit is the first the one. > Modfiy and will send out version 6. > > >> +# set CONFIG_RTE_BUILD_COMBINE_LIBS=y in <dpdk-build-dir>/.config >> > This is commented out but I think it is a required step, so maybe it > should have > a comment say "and now edit this file" > Modfiy and will send out version 6. > + >> +Note: If non-intel SFP's are used in NIC, then go to >> <dpdk-build-dir>/.config >> +and set CONFIG_RTE_LIBRTE_IXGBE_ALLOW_UNSUPPORTED_SFP=y >> + >> +$ cd <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 >> > I had to use sudo for this > sudo sh -c 'echo 1024 > > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages' > Modfiy and will send out version 6. > > +# 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 >> > Should we spell out doing "ls /sys/devices/system/node" to discover how > many nodes you have ? > Modfiy and will send out version 6. > + >> +$ sudo mkdir /mnt/huge >> +$ sudo mount -t hugetlbfs nodev /mnt/huge >> +# To load uio driver >> +$ sudo /sbin/modprobe uio >> +$ ulimit -Sn 2048 >> + >> +$ cd <dpdk-dir> >> +$ sudo insmod ./build/build/lib/librte_eal/linuxapp/igb_uio/igb_uio.ko >> + >> +$ rmmod ixgbe >> > should this be sudo ? > Modfiy and will send out version 6. > +$ modprobe ixgbe >> > should this be sudo > Modfiy and will send out version 6. > +# If the SFP's used are non-intel, then >> +$ modprobe ixgbe allow_unsupported_sfp=1 >> > should this be sudo > Modfiy and will send out version 6. > + >> +$ cd <dpdk-dir> >> +$ ./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 >> should there be an example of the output like below but for a real device >> ? >> > > Network devices using IGB_UIO driver > ==================================== > <none> > > Network devices using kernel driver > =================================== > 0000:06:00.0 'NetXtreme BCM5761 Gigabit Ethernet PCIe' if=eth0 drv=tg3 > unused=<none> *Active* > > Other network devices > ===================== > <none> > > > >> +# 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 >> > Should this list cd to your ODP directory here because the previous > instructions are that detailed? > Modfiy and will send out version 6. > +$ ./bootstrap >> +$ ./configure --with-platform=linux-dpdk 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" >> > Can we change all the <dpdk-build-dir> to be using the defaults - in this > case basically ../dpdk so that it can be blindly cut and paste - OR maybe > better in the instructions set an export at the beginning that points at > DPDK and use $dpdk-build-dir. Alao a not that you must use full paths not > relative ? > Already given the default "dpdk" and "build" in the example. Full path is clear and using relative path is users choice > +# For example >> +$ ./configure --with-platform=linux-dpdk LDFLAGS=-L/root/dpdk/build/lib >> CFLAGS="-include /root/dpdk/build/include/rte_config.h >> -I/root/dpdk/build/include -I/root/dpdk/build/include/arch >> -I/root/dpdk/build/include/exec-env" >> +$ make clean >> +$ make >> + >> +# Commands to test >> +l2fwding app - ./test/l2fwd/odp_l2fwd -i 0,1 -m 0 -c 2 >> +loopback app - ./test/packet/odp_pktio -i 0,1 -m 0 -c 2 >> + >> + -i 0,1 - interface number >> + -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 *)ð->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, ð_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..d8d127f >> --- /dev/null >> +++ b/platform/linux-dpdk/odp_packet_io.c >> @@ -0,0 +1,419 @@ >> +/* 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; >> + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); >> + /* 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; >> + } >> + >> + ODP_DBG("Allocating dpdk pktio\n"); >> + >> + 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); >> + >> + 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; >> + } >> + >> + 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)) { >> + res = close_pkt_dpdk(&entry->s.pkt_dpdk); >> + 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); >> + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, len); >> + 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); >> + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, >> + pkt_table, len); >> + 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 >> > > > > -- > *Mike Holmes* > Linaro Technical Manager / Lead > LNG - ODP >
On 18 July 2014 17:24, Santosh Shukla <santosh.shukla@linaro.org> wrote: > Why can't we remove DPDK build method from odp-dpdk readme, with one > note that user should aware of dpdk env/build details. I did dpdk > setup on non-ubuntu distro (centos) and it asks for little different > package dependency for me. Dependency may vary from one distro to > another (a little though). > We can make a note and leave there. Just to help new dpdk users, I have mentioned what was done at Ubuntu to get started. Updated the README accordingly. Please check version 6 which will be sent shortly. > On 18 July 2014 03:11, Mike Holmes <mike.holmes@linaro.org> wrote: > > > > > > > > On 17 July 2014 15:03, <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 | 76 ++++ > >> 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 | 419 > >> ++++++++++++++++++++ > >> platform/linux-dpdk/odp_queue.c | 435 > >> +++++++++++++++++++++ > >> 20 files changed, 2955 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..8f5b94b > >> --- /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 > >> +#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 > >> + > >> +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..3578512 > >> --- /dev/null > >> +++ b/platform/linux-dpdk/README > >> @@ -0,0 +1,76 @@ > >> +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-dir> > >> +# 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 > >> + > >> +$ cd <dpdk-dir> > >> + > >> +# Only for the first time > >> +$ make config T=x86_64-default-linuxapp-gcc > >> +# above command will generate build directory as ./build by default in > >> +# <dpdk-dir> which can be overridden by specifying O=my_build_dir > option > >> as > >> +$ make config T=x86_64-default-linuxapp-gcc O=my_sdk_build_dir > > > > For the above there are two make commands listed, it is not clear which > is > > needed. > > I assumed that that iit is the first the one. > > > >> > >> +# set CONFIG_RTE_BUILD_COMBINE_LIBS=y in <dpdk-build-dir>/.config > > > > This is commented out but I think it is a required step, so maybe it > should > > have > > a comment say "and now edit this file" > >> > >> + > >> +Note: If non-intel SFP's are used in NIC, then go to > >> <dpdk-build-dir>/.config > >> +and set CONFIG_RTE_LIBRTE_IXGBE_ALLOW_UNSUPPORTED_SFP=y > >> + > >> +$ cd <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 > > > > I had to use sudo for this > > sudo sh -c '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 > > > > Should we spell out doing "ls /sys/devices/system/node" to discover how > > many nodes you have ? > >> > >> + > >> +$ sudo mkdir /mnt/huge > >> +$ sudo mount -t hugetlbfs nodev /mnt/huge > >> +# To load uio driver > >> +$ sudo /sbin/modprobe uio > >> +$ ulimit -Sn 2048 > >> + > >> +$ cd <dpdk-dir> > >> +$ sudo insmod ./build/build/lib/librte_eal/linuxapp/igb_uio/igb_uio.ko > >> + > >> +$ rmmod ixgbe > > > > should this be sudo ? > >> > >> +$ modprobe ixgbe > > > > should this be sudo > >> > >> +# If the SFP's used are non-intel, then > >> +$ modprobe ixgbe allow_unsupported_sfp=1 > > > > should this be sudo > >> > >> + > >> +$ cd <dpdk-dir> > >> +$ ./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 > >> should there be an example of the output like below but for a real > device > >> ? > > > > > > Network devices using IGB_UIO driver > > ==================================== > > <none> > > > > Network devices using kernel driver > > =================================== > > 0000:06:00.0 'NetXtreme BCM5761 Gigabit Ethernet PCIe' if=eth0 drv=tg3 > > unused=<none> *Active* > > > > Other network devices > > ===================== > > <none> > > > > > >> > >> +# 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 > > > > Should this list cd to your ODP directory here because the previous > > instructions are that detailed? > >> > >> +$ ./bootstrap > >> +$ ./configure --with-platform=linux-dpdk 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" > > > > Can we change all the <dpdk-build-dir> to be using the defaults - in > this > > case basically ../dpdk so that it can be blindly cut and paste - OR maybe > > better in the instructions set an export at the beginning that points at > > DPDK and use $dpdk-build-dir. Alao a not that you must use full paths not > > relative ? > >> > >> +# For example > >> +$ ./configure --with-platform=linux-dpdk LDFLAGS=-L/root/dpdk/build/lib > >> CFLAGS="-include /root/dpdk/build/include/rte_config.h > >> -I/root/dpdk/build/include -I/root/dpdk/build/include/arch > >> -I/root/dpdk/build/include/exec-env" > >> +$ make clean > >> +$ make > >> + > >> +# Commands to test > >> +l2fwding app - ./test/l2fwd/odp_l2fwd -i 0,1 -m 0 -c 2 > >> +loopback app - ./test/packet/odp_pktio -i 0,1 -m 0 -c 2 > >> + > >> + -i 0,1 - interface number > >> + -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 *)ð->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, ð_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..d8d127f > >> --- /dev/null > >> +++ b/platform/linux-dpdk/odp_packet_io.c > >> @@ -0,0 +1,419 @@ > >> +/* 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; > >> + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); > >> + /* 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; > >> + } > >> + > >> + ODP_DBG("Allocating dpdk pktio\n"); > >> + > >> + 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); > >> + > >> + 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; > >> + } > >> + > >> + 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)) { > >> + res = close_pkt_dpdk(&entry->s.pkt_dpdk); > >> + 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); > >> + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, len); > >> + 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); > >> + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, > >> + pkt_table, len); > >> + 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 > > > > > > > > > > -- > > Mike Holmes > > Linaro Technical Manager / Lead > > LNG - ODP > > > > _______________________________________________ > > lng-odp mailing list > > lng-odp@lists.linaro.org > > http://lists.linaro.org/mailman/listinfo/lng-odp > > >
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..8f5b94b --- /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 +#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 + +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..3578512 --- /dev/null +++ b/platform/linux-dpdk/README @@ -0,0 +1,76 @@ +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-dir> +# 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 + +$ cd <dpdk-dir> + +# Only for the first time +$ make config T=x86_64-default-linuxapp-gcc +# above command will generate build directory as ./build by default in +# <dpdk-dir> which can be overridden by specifying O=my_build_dir option as +$ make config T=x86_64-default-linuxapp-gcc O=my_sdk_build_dir +# set CONFIG_RTE_BUILD_COMBINE_LIBS=y in <dpdk-build-dir>/.config + +Note: If non-intel SFP's are used in NIC, then go to <dpdk-build-dir>/.config +and set CONFIG_RTE_LIBRTE_IXGBE_ALLOW_UNSUPPORTED_SFP=y + +$ cd <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 + +$ cd <dpdk-dir> +$ sudo 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-dir> +$ ./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 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" +# For example +$ ./configure --with-platform=linux-dpdk LDFLAGS=-L/root/dpdk/build/lib CFLAGS="-include /root/dpdk/build/include/rte_config.h -I/root/dpdk/build/include -I/root/dpdk/build/include/arch -I/root/dpdk/build/include/exec-env" +$ make clean +$ make + +# Commands to test +l2fwding app - ./test/l2fwd/odp_l2fwd -i 0,1 -m 0 -c 2 +loopback app - ./test/packet/odp_pktio -i 0,1 -m 0 -c 2 + + -i 0,1 - interface number + -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 *)ð->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, ð_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..d8d127f --- /dev/null +++ b/platform/linux-dpdk/odp_packet_io.c @@ -0,0 +1,419 @@ +/* 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; + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); + /* 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; + } + + ODP_DBG("Allocating dpdk pktio\n"); + + 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); + + 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; + } + + 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)) { + res = close_pkt_dpdk(&entry->s.pkt_dpdk); + 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); + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, len); + 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); + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, + pkt_table, len); + 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); +}