Message ID | 1405103703-15084-1-git-send-email-venkatesh.vivekanandan@linaro.org |
---|---|
State | New |
Headers | show |
Adds whitespace errors when applied. Also needs a README like the one in linux-keystone to indicate such things as setting ./configure --with-platform=linux-dpdk And how to then ensure dpdk is installed to resolve things like /usr/include/stdc-predef.h:59:1: fatal error: ../../../dpdk/build/include/rte_config.h: No such file or directory On 11 July 2014 14:35, <venkatesh.vivekanandan@linaro.org> wrote: > From: Vincent Hsu <vincent.hsu@linaro.org> > > Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org> > --- > platform/linux-dpdk/Makefile | 158 ++++++ > platform/linux-dpdk/Makefile.inc | 7 + > platform/linux-dpdk/include/api/odp_buffer.h | 101 ++++ > platform/linux-dpdk/include/api/odp_buffer_pool.h | 99 ++++ > platform/linux-dpdk/include/api/odp_packet.h | 228 +++++++++ > platform/linux-dpdk/include/api/odp_pktio_types.h | 45 ++ > platform/linux-dpdk/include/odp_buffer_internal.h | 79 +++ > .../linux-dpdk/include/odp_buffer_pool_internal.h | 90 ++++ > platform/linux-dpdk/include/odp_packet_dpdk.h | 88 ++++ > platform/linux-dpdk/include/odp_packet_internal.h | 140 +++++ > .../linux-dpdk/include/odp_packet_io_internal.h | 52 ++ > platform/linux-dpdk/source/odp_buffer.c | 102 ++++ > platform/linux-dpdk/source/odp_buffer_pool.c | 156 ++++++ > platform/linux-dpdk/source/odp_init.c | 113 +++++ > platform/linux-dpdk/source/odp_packet.c | 374 ++++++++++++++ > platform/linux-dpdk/source/odp_packet_dpdk.c | 177 +++++++ > platform/linux-dpdk/source/odp_packet_io.c | 561 > +++++++++++++++++++++ > platform/linux-dpdk/source/odp_queue.c | 435 ++++++++++++++++ > 18 files changed, 3005 insertions(+) > create mode 100644 platform/linux-dpdk/Makefile > create mode 100644 platform/linux-dpdk/Makefile.inc > create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h > create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h > create mode 100644 platform/linux-dpdk/include/api/odp_packet.h > create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h > create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h > create mode 100644 platform/linux-dpdk/include/odp_buffer_pool_internal.h > create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h > create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h > create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h > create mode 100644 platform/linux-dpdk/source/odp_buffer.c > create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c > create mode 100644 platform/linux-dpdk/source/odp_init.c > create mode 100644 platform/linux-dpdk/source/odp_packet.c > create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c > create mode 100644 platform/linux-dpdk/source/odp_packet_io.c > create mode 100644 platform/linux-dpdk/source/odp_queue.c > > diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile > new file mode 100644 > index 0000000..bf8d0b3 > --- /dev/null > +++ b/platform/linux-dpdk/Makefile > @@ -0,0 +1,158 @@ > +## Copyright (c) 2013, Linaro Limited > +## All rights reserved. > +## > +## Redistribution and use in source and binary forms, with or without > +## modification, are permitted provided that the following conditions are > met: > +## > +## * Redistributions of source code must retain the above copyright > notice, this > +## list of conditions and the following disclaimer. > +## > +## * Redistributions in binary form must reproduce the above copyright > notice, this > +## list of conditions and the following disclaimer in the > documentation and/or > +## other materials provided with the distribution. > +## > +## * Neither the name of Linaro Limited nor the names of its > contributors may be > +## used to endorse or promote products derived from this software > without specific > +## prior written permission. > +## > +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > "AS IS" AND > +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > IMPLIED > +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE > LIABLE > +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > CONSEQUENTIAL > +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE > GOODS OR > +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > HOWEVER > +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > LIABILITY, > +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE USE > +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > +.DEFAULT_GOAL := libs > + > +ODP_ROOT = ../.. > +LIB_DIR = ./lib > +DOC_DIR = ./doc > + > +LINUX_GENERIC_DIR = ../linux-generic > + > +RTE_SDK ?= $(abspath $(ODP_ROOT)/../dpdk) > +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build) > +RTE_LIB ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a) > + > +PLAT_CFLAGS = -include $(RTE_OUTPUT)/include/rte_config.h > +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include > +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch > +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env > +PLAT_CFLAGS += -msse4.2 > + > +EXTRA_CFLAGS += $(PLAT_CFLAGS) > +EXTRA_CFLAGS += -I./include > +EXTRA_CFLAGS += -I./include/api > +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include > +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api > +EXTRA_CFLAGS += -I$(ODP_ROOT)/include > + > +include $(ODP_ROOT)/Makefile.inc > +STATIC_LIB = ./lib/libodp.a > + > +# > +# Object files > +# > +OBJS = > +OBJS += $(OBJ_DIR)/odp_barrier.o > +OBJS += $(OBJ_DIR)/odp_buffer.o > +OBJS += $(OBJ_DIR)/odp_buffer_pool.o > +OBJS += $(OBJ_DIR)/odp_coremask.o > +OBJS += $(OBJ_DIR)/odp_init.o > +OBJS += $(OBJ_DIR)/odp_linux.o > +OBJS += $(OBJ_DIR)/odp_packet.o > +OBJS += $(OBJ_DIR)/odp_packet_flags.o > +OBJS += $(OBJ_DIR)/odp_packet_io.o > +OBJS += $(OBJ_DIR)/odp_packet_socket.o > +OBJS += $(OBJ_DIR)/odp_queue.o > +OBJS += $(OBJ_DIR)/odp_schedule.o > +OBJS += $(OBJ_DIR)/odp_shared_memory.o > +OBJS += $(OBJ_DIR)/odp_spinlock.o > +OBJS += $(OBJ_DIR)/odp_system_info.o > +OBJS += $(OBJ_DIR)/odp_thread.o > +OBJS += $(OBJ_DIR)/odp_ticketlock.o > +OBJS += $(OBJ_DIR)/odp_time.o > +OBJS += $(OBJ_DIR)/odp_timer.o > +OBJS += $(OBJ_DIR)/odp_ring.o > +OBJS += $(OBJ_DIR)/odp_rwlock.o > +OBJS += $(OBJ_DIR)/odp_packet_dpdk.o > + > +DEPS = $(OBJS:.o=.d) > + > +.PHONY: all > +all: libs docs > + > +-include $(DEPS) > + > +#$(OBJ_DIR): > +# $(MKDIR) $(OBJ_DIR) > + > +$(LIB_DIR): > + $(MKDIR) $(LIB_DIR) > + > +$(DOC_DIR): > + $(MKDIR) $(DOC_DIR)/html > + $(MKDIR) $(DOC_DIR)/latex > + > +# > +# Compile rules > +# > +vpath %.c source:$(LINUX_GENERIC_DIR)/source > + > +$(OBJ_DIR)/%.o: %.c > + $(ECHO) " CC $<" > + $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $< > + > +# > +# Lib rule > +# > +$(OBJ_DIR)/libodp.o: $(OBJS) > + $(ECHO) " LD $@" > + $(LD) -r -o $@ $(OBJS) $(RTE_LIB) > + > +$(STATIC_LIB): $(OBJ_DIR)/libodp.o > + $(ECHO) " AR $@" > + $(AR) -cr $@ $(OBJ_DIR)/libodp.o > + > + > +clean: > + $(RMDIR) $(OBJ_DIR) > + $(RMDIR) $(LIB_DIR) > + $(RMDIR) $(DOC_DIR) > + $(RM) Doxyfile > + > +Doxyfile: Doxyfile.in > + doxygen -u - < $< > $@ > + > +.PHONY: docs > +docs: $(DOC_DIR) Doxyfile ./include/odp*.h > + doxygen > + > +.PHONY: docs_install > +docs_install: docs > + $(COPY) doc $(DESTDIR) > + > +.PHONY: pdf > +pdf: docs > + make --directory doc/latex refman.pdf 1> /dev/null > + > +.PHONY: libs > +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB) > + > +.PHONY: lib_install > +lib_install: libs > + install -d $(DESTDIR)/lib > + install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/ > + > +.PHONY: headers_install > +headers_install: libs > + $(ECHO) Installing headers to $(DESTDIR)/include > + $(COPY) $(ODP_ROOT)/include $(DESTDIR) > + $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/ > + $(COPY) include/api/* $(DESTDIR)/include/ > + > +install: lib_install headers_install > diff --git a/platform/linux-dpdk/Makefile.inc > b/platform/linux-dpdk/Makefile.inc > new file mode 100644 > index 0000000..fe7679b > --- /dev/null > +++ b/platform/linux-dpdk/Makefile.inc > @@ -0,0 +1,7 @@ > +# Copyright (c) 2013, Linaro Limited > +# All rights reserved. > +# > +# SPDX-License-Identifier: BSD-3-Clause > + > +STD_LIBS += -ldl > + > diff --git a/platform/linux-dpdk/include/api/odp_buffer.h > b/platform/linux-dpdk/include/api/odp_buffer.h > new file mode 100644 > index 0000000..286d9e6 > --- /dev/null > +++ b/platform/linux-dpdk/include/api/odp_buffer.h > @@ -0,0 +1,101 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > + > +/** > + * @file > + * > + * ODP buffer descriptor > + */ > + > +#ifndef ODP_BUFFER_H_ > +#define ODP_BUFFER_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > + > + > +#include <odp_std_types.h> > + > + > + > + > + > +/** > + * ODP buffer > + */ > +typedef unsigned long odp_buffer_t; > + > + > +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */ > + > + > +/** > + * Buffer start address > + * > + * @param buf Buffer handle > + * > + * @return Buffer start address > + */ > +void *odp_buffer_addr(odp_buffer_t buf); > + > +/** > + * Buffer maximum data size > + * > + * @param buf Buffer handle > + * > + * @return Buffer maximum data size > + */ > +size_t odp_buffer_size(odp_buffer_t buf); > + > +/** > + * Buffer type > + * > + * @param buf Buffer handle > + * > + * @return Buffer type > + */ > +int odp_buffer_type(odp_buffer_t buf); > + > +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */ > +#define ODP_BUFFER_TYPE_RAW 0 /**< Raw buffer */ > +#define ODP_BUFFER_TYPE_PACKET 1 /**< Packet buffer */ > +#define ODP_BUFFER_TYPE_TIMER 2 /**< Timer buffer */ > + > +/** > + * Tests if buffer is part of a scatter/gather list > + * > + * @param buf Buffer handle > + * > + * @return 1 if belongs to a scatter list, otherwise 0 > + */ > +int odp_buffer_is_scatter(odp_buffer_t buf); > + > +/** > + * Tests if buffer is valid > + * > + * @param buf Buffer handle > + * > + * @return 1 if valid, otherwise 0 > + */ > +int odp_buffer_is_valid(odp_buffer_t buf); > + > +/** > + * Print buffer metadata to STDOUT > + * > + * @param buf Buffer handle > + * > + */ > +void odp_buffer_print(odp_buffer_t buf); > + > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h > b/platform/linux-dpdk/include/api/odp_buffer_pool.h > new file mode 100644 > index 0000000..4b75cf5 > --- /dev/null > +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h > @@ -0,0 +1,99 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > + > +/** > + * @file > + * > + * ODP buffer pool > + */ > + > +#ifndef ODP_BUFFER_POOL_H_ > +#define ODP_BUFFER_POOL_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > + > + > +#include <odp_std_types.h> > +#include <odp_buffer.h> > + > +/** Maximum queue name lenght in chars */ > +#define ODP_BUFFER_POOL_NAME_LEN 32 > + > +/** Invalid buffer pool */ > +#define ODP_BUFFER_POOL_INVALID (0xffffffff) > + > +/** ODP buffer pool */ > +typedef unsigned long odp_buffer_pool_t; > + > + > +/** > + * Create a buffer pool > + * > + * @param name Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1 > chars) > + * @param base_addr Pool base address > + * @param size Pool size in bytes > + * @param buf_size Buffer size in bytes > + * @param buf_align Minimum buffer alignment > + * @param buf_type Buffer type > + * > + * @return Buffer pool handle > + */ > +odp_buffer_pool_t odp_buffer_pool_create(const char *name, > + void *base_addr, uint64_t size, > + size_t buf_size, size_t buf_align, > + int buf_type); > + > + > +/** > + * Find a buffer pool by name > + * > + * @param name Name of the pool > + * > + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found. > + */ > +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name); > + > + > +/** > + * Print buffer pool info > + * > + * @param pool Pool handle > + * > + */ > +void odp_buffer_pool_print(odp_buffer_pool_t pool); > + > + > + > +/** > + * Buffer alloc > + * > + * @param pool Pool handle > + * > + * @return Buffer handle or ODP_BUFFER_INVALID > + */ > +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool); > + > + > +/** > + * Buffer free > + * > + * @param buf Buffer handle > + * > + */ > +void odp_buffer_free(odp_buffer_t buf); > + > + > + > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-dpdk/include/api/odp_packet.h > b/platform/linux-dpdk/include/api/odp_packet.h > new file mode 100644 > index 0000000..bdb3417 > --- /dev/null > +++ b/platform/linux-dpdk/include/api/odp_packet.h > @@ -0,0 +1,228 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > + > +/** > + * @file > + * > + * ODP packet descriptor > + */ > + > +#ifndef ODP_PACKET_H_ > +#define ODP_PACKET_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp_buffer.h> > + > + > +/** > + * ODP packet descriptor > + */ > +typedef unsigned long odp_packet_t; > + > + > +/** Invalid packet */ > +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID > + > +/** Invalid offset */ > +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1) > + > + > +/** > + * Initialize the packet > + * > + * Needs to be called if the user allocates a packet buffer, i.e. the > packet > + * has not been received from I/O through ODP. > + * > + * @param pkt Packet handle > + */ > +void odp_packet_init(odp_packet_t pkt); > + > +/** > + * Convert from packet handle to buffer handle > + * > + * @param buf Buffer handle > + * > + * @return Packet handle > + */ > +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf); > + > +/** > + * Convert from buffer handle to packet handle > + * > + * @param pkt Packet handle > + * > + * @return Buffer handle > + */ > +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt); > + > +/** > + * Set the packet length > + * > + * @param pkt Packet handle > + * @param len Length of packet in bytes > + */ > +void odp_packet_set_len(odp_packet_t pkt, size_t len); > + > +/** > + * Get the packet length > + * > + * @param pkt Packet handle > + * > + * @return Packet length in bytes > + */ > +size_t odp_packet_get_len(odp_packet_t pkt); > + > +/** > + * Get address to the start of the packet buffer > + * > + * The address of the packet buffer is not necessarily the same as the > start > + * address of the received frame, e.g. an eth frame may be offset by 2 or > 6 > + * bytes to ensure 32 or 64-bit alignment of the IP header. > + * Use odp_packet_l2(pkt) to get the start address of a received valid > frame > + * or odp_packet_start(pkt) to get the start address even if no valid L2 > header > + * could be found. > + * > + * @param pkt Packet handle > + * > + * @return Pointer to the start of the packet buffer > + * > + * @see odp_packet_l2(), odp_packet_start() > + */ > +uint8_t *odp_packet_buf_addr(odp_packet_t pkt); > + > +/** > + * Get pointer to the start of the received frame > + * > + * The address of the packet buffer is not necessarily the same as the > start > + * address of the received frame, e.g. an eth frame may be offset by 2 or > 6 > + * bytes to ensure 32 or 64-bit alignment of the IP header. > + * Use odp_packet_l2(pkt) to get the start address of a received valid > eth frame > + * > + * odp_packet_start() will always return a pointer to the start of the > frame, > + * even if the frame is unrecognized and no valid L2 header could be > found. > + * > + * @param pkt Packet handle > + * > + * @return Pointer to the start of the received frame > + * > + * @see odp_packet_l2(), odp_packet_buf_addr() > + */ > +uint8_t *odp_packet_start(odp_packet_t pkt); > + > +/** > + * Get pointer to the start of the L2 frame > + * > + * The L2 frame header address is not necessarily the same as the address > of the > + * packet buffer, see odp_packet_buf_addr() > + * > + * @param pkt Packet handle > + * > + * @return Pointer to L2 header or NULL if not found > + * > + * @see odp_packet_buf_addr(), odp_packet_start() > + */ > +uint8_t *odp_packet_l2(odp_packet_t pkt); > + > +/** > + * Return the byte offset from the packet buffer to the L2 frame > + * > + * @param pkt Packet handle > + * > + * @return L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found > + */ > +size_t odp_packet_l2_offset(odp_packet_t pkt); > + > +/** > + * Set the byte offset to the L2 frame > + * > + * @param pkt Packet handle > + * @param offset L2 byte offset > + */ > +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset); > + > + > +/** > + * Get pointer to the start of the L3 packet > + * > + * @param pkt Packet handle > + * > + * @return Pointer to L3 packet or NULL if not found > + * > + */ > +uint8_t *odp_packet_l3(odp_packet_t pkt); > + > +/** > + * Return the byte offset from the packet buffer to the L3 packet > + * > + * @param pkt Packet handle > + * > + * @return L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found > + */ > +size_t odp_packet_l3_offset(odp_packet_t pkt); > + > +/** > + * Set the byte offset to the L3 packet > + * > + * @param pkt Packet handle > + * @param offset L3 byte offset > + */ > +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset); > + > + > +/** > + * Get pointer to the start of the L4 packet > + * > + * @param pkt Packet handle > + * > + * @return Pointer to L4 packet or NULL if not found > + * > + */ > +uint8_t *odp_packet_l4(odp_packet_t pkt); > + > +/** > + * Return the byte offset from the packet buffer to the L4 packet > + * > + * @param pkt Packet handle > + * > + * @return L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found > + */ > +size_t odp_packet_l4_offset(odp_packet_t pkt); > + > +/** > + * Set the byte offset to the L4 packet > + * > + * @param pkt Packet handle > + * @param offset L4 byte offset > + */ > +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset); > + > +/** > + * Print (debug) information about the packet > + * > + * @param pkt Packet handle > + */ > +void odp_packet_print(odp_packet_t pkt); > + > +/** > + * Copy contents and metadata from pkt_src to pkt_dst > + * Useful when creating copies of packets > + * > + * @param pkt_dst Destination packet > + * @param pkt_src Source packet > + * > + * @return 0 if successful > + */ > +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h > b/platform/linux-dpdk/include/api/odp_pktio_types.h > new file mode 100644 > index 0000000..b23e6da > --- /dev/null > +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h > @@ -0,0 +1,45 @@ > + > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef ODP_PKTIO_TYPES_H > +#define ODP_PKTIO_TYPES_H > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/* We should ensure that future enum values will never overlap, otherwise > + * applications that want netmap suport might get in trouble if the odp > lib > + * was not built with netmap support and there are more types define below > + */ > + > +typedef enum { > + ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1, > + ODP_PKTIO_TYPE_SOCKET_MMSG, > + ODP_PKTIO_TYPE_SOCKET_MMAP, > + ODP_PKTIO_TYPE_NETMAP, > + ODP_PKTIO_TYPE_DPDK, > +} odp_pktio_type_t; > + > +#include <odp_pktio_socket.h> > +#ifdef ODP_HAVE_NETMAP > +#include <odp_pktio_netmap.h> > +#endif > + > +typedef union odp_pktio_params_t { > + odp_pktio_type_t type; > + socket_params_t sock_params; > +#ifdef ODP_HAVE_NETMAP > + netmap_params_t nm_params; > +#endif > +} odp_pktio_params_t; > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h > b/platform/linux-dpdk/include/odp_buffer_internal.h > new file mode 100644 > index 0000000..a47107c > --- /dev/null > +++ b/platform/linux-dpdk/include/odp_buffer_internal.h > @@ -0,0 +1,79 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > + > +/** > + * @file > + * > + * ODP buffer descriptor - implementation internal > + */ > + > +#ifndef ODP_BUFFER_INTERNAL_H_ > +#define ODP_BUFFER_INTERNAL_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp_std_types.h> > +#include <odp_atomic.h> > +#include <odp_buffer_pool.h> > +#include <odp_buffer.h> > +#include <odp_debug.h> > +#include <odp_align.h> > +#include <rte_mbuf.h> > + > +/* TODO: move these to correct files */ > + > +typedef uint64_t odp_phys_addr_t; > + > +#define ODP_BUFFER_MAX_INDEX (ODP_BUFFER_MAX_BUFFERS - 2) > +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1) > + > +#define ODP_BUFS_PER_CHUNK 16 > +#define ODP_BUFS_PER_SCATTER 4 > + > +#define ODP_BUFFER_TYPE_CHUNK 0xffff > + > + > +#define ODP_BUFFER_POOL_BITS 4 > +#define ODP_BUFFER_INDEX_BITS (32 - ODP_BUFFER_POOL_BITS) > +#define ODP_BUFFER_MAX_POOLS (1 << ODP_BUFFER_POOL_BITS) > +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS) > + > +typedef union odp_buffer_bits_t { > + uint32_t u32; > + odp_buffer_t handle; > + > + struct { > + uint32_t pool:ODP_BUFFER_POOL_BITS; > + uint32_t index:ODP_BUFFER_INDEX_BITS; > + }; > +} odp_buffer_bits_t; > + > + > +/* forward declaration */ > +struct odp_buffer_hdr_t; > + > + > +typedef struct rte_mbuf odp_buffer_hdr_t; > + > + > +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf); > + > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > + > + > + > + > + > + > + > diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h > b/platform/linux-dpdk/include/odp_buffer_pool_internal.h > new file mode 100644 > index 0000000..1a36655 > --- /dev/null > +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h > @@ -0,0 +1,90 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > + > +/** > + * @file > + * > + * ODP buffer pool - internal header > + */ > + > +#ifndef ODP_BUFFER_POOL_INTERNAL_H_ > +#define ODP_BUFFER_POOL_INTERNAL_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp_std_types.h> > +#include <odp_buffer_pool.h> > +#include <odp_buffer_internal.h> > +#include <odp_align.h> > +#include <odp_hints.h> > +#include <odp_config.h> > +#include <odp_debug.h> > + > +/* for DPDK */ > +#include <rte_mempool.h> > + > +/* Use ticketlock instead of spinlock */ > +#define POOL_USE_TICKETLOCK > + > +/* Extra error checks */ > +/* #define POOL_ERROR_CHECK */ > + > + > +#ifdef POOL_USE_TICKETLOCK > +#include <odp_ticketlock.h> > +#else > +#include <odp_spinlock.h> > +#endif > + > + > +struct pool_entry_s { > +#ifdef POOL_USE_TICKETLOCK > + odp_ticketlock_t lock ODP_ALIGNED_CACHE; > +#else > + odp_spinlock_t lock ODP_ALIGNED_CACHE; > +#endif > + > + uint64_t free_bufs; > + char name[ODP_BUFFER_POOL_NAME_LEN]; > + > + > + odp_buffer_pool_t pool ODP_ALIGNED_CACHE; > + uintptr_t buf_base; > + size_t buf_size; > + size_t buf_offset; > + uint64_t num_bufs; > + void *pool_base_addr; > + uint64_t pool_size; > + size_t payload_size; > + size_t payload_align; > + int buf_type; > + size_t hdr_size; > +}; > + > + > +extern void *pool_entry_ptr[]; > + > + > +static inline void *get_pool_entry(odp_buffer_pool_t pool_id) > +{ > + return pool_entry_ptr[pool_id]; > +} > + > + > +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf) > +{ > + return (odp_buffer_hdr_t *)buf; > +} > + > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h > b/platform/linux-dpdk/include/odp_packet_dpdk.h > new file mode 100644 > index 0000000..0b3db08 > --- /dev/null > +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h > @@ -0,0 +1,88 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef ODP_PACKET_DPDK_H > +#define ODP_PACKET_DPDK_H > + > +#include <stdint.h> > +#include <net/if.h> > + > +#include <helper/odp_eth.h> > +#include <helper/odp_packet_helper.h> > +#include <odp_align.h> > +#include <odp_debug.h> > +#include <odp_packet.h> > +#include <odp_packet_internal.h> > +#include <odp_buffer_pool.h> > +#include <odp_buffer_pool_internal.h> > +#include <odp_buffer_internal.h> > +#include <odp_std_types.h> > + > +#include <rte_config.h> > +#include <rte_memory.h> > +#include <rte_memzone.h> > +#include <rte_launch.h> > +#include <rte_tailq.h> > +#include <rte_eal.h> > +#include <rte_per_lcore.h> > +#include <rte_lcore.h> > +#include <rte_branch_prediction.h> > +#include <rte_prefetch.h> > +#include <rte_cycles.h> > +#include <rte_errno.h> > +#include <rte_debug.h> > +#include <rte_log.h> > +#include <rte_byteorder.h> > +#include <rte_pci.h> > +#include <rte_random.h> > +#include <rte_ether.h> > +#include <rte_ethdev.h> > +#include <rte_hash.h> > +#include <rte_jhash.h> > +#include <rte_hash_crc.h> > + > + > +#define ODP_DPDK_MODE_HW 0 > +#define ODP_DPDK_MODE_SW 1 > + > +#define DPDK_BLOCKING_IO > + > +/** Packet socket using dpdk mmaped rings for both Rx and Tx */ > +typedef struct { > + odp_buffer_pool_t pool; > + > + /********************************/ > + char ifname[32]; > + uint8_t portid; > + uint16_t queueid; > +} pkt_dpdk_t; > + > +/** > + * Configure an interface to work in dpdk mode > + */ > +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, > + odp_buffer_pool_t pool); > + > +/** > + * Switch interface from dpdk mode to normal mode > + */ > +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk); > + > +/** > + * Receive packets using dpdk > + */ > +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], > + unsigned len); > + > +/** > + * Send packets using dpdk > + */ > +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], > + unsigned len); > + > +int odp_init_dpdk(void); > +#endif > + > diff --git a/platform/linux-dpdk/include/odp_packet_internal.h > b/platform/linux-dpdk/include/odp_packet_internal.h > new file mode 100644 > index 0000000..d9057a2 > --- /dev/null > +++ b/platform/linux-dpdk/include/odp_packet_internal.h > @@ -0,0 +1,140 @@ > +/* Copyright (c) 2014, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > + > +/** > + * @file > + * > + * ODP packet descriptor - implementation internal > + */ > + > +#ifndef ODP_PACKET_INTERNAL_H_ > +#define ODP_PACKET_INTERNAL_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp_align.h> > +#include <odp_debug.h> > +#include <odp_buffer_internal.h> > +#include <odp_buffer_pool_internal.h> > +#include <odp_packet.h> > +#include <odp_packet_io.h> > + > +/** > + * Packet input & protocol flags > + */ > +typedef union { > + /* All input flags */ > + uint32_t all; > + > + struct { > + /* Bitfield flags for each protocol */ > + uint32_t l2:1; /**< known L2 protocol present */ > + uint32_t l3:1; /**< known L3 protocol present */ > + uint32_t l4:1; /**< known L4 protocol present */ > + > + uint32_t eth:1; /**< Ethernet */ > + uint32_t jumbo:1; /**< Jumbo frame */ > + uint32_t vlan:1; /**< VLAN hdr found */ > + uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */ > + > + uint32_t arp:1; /**< ARP */ > + > + uint32_t ipv4:1; /**< IPv4 */ > + uint32_t ipv6:1; /**< IPv6 */ > + uint32_t ipfrag:1; /**< IP fragment */ > + uint32_t ipopt:1; /**< IP optional headers */ > + uint32_t ipsec:1; /**< IPSec decryption may be needed > */ > + > + uint32_t udp:1; /**< UDP */ > + uint32_t tcp:1; /**< TCP */ > + uint32_t sctp:1; /**< SCTP */ > + uint32_t icmp:1; /**< ICMP */ > + }; > +} input_flags_t; > + > +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t), > INPUT_FLAGS_SIZE_ERROR); > + > +/** > + * Packet error flags > + */ > +typedef union { > + /* All error flags */ > + uint32_t all; > + > + struct { > + /* Bitfield flags for each detected error */ > + uint32_t frame_len:1; /**< Frame length error */ > + uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD */ > + uint32_t ip_err:1; /**< IP error, checks TBD */ > + uint32_t tcp_err:1; /**< TCP error, checks TBD */ > + uint32_t udp_err:1; /**< UDP error, checks TBD */ > + }; > +} error_flags_t; > + > +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t), > ERROR_FLAGS_SIZE_ERROR); > + > +/** > + * Packet output flags > + */ > +typedef union { > + /* All output flags */ > + uint32_t all; > + > + struct { > + /* Bitfield flags for each output option */ > + uint32_t l4_chksum:1; /**< Request L4 checksum calculation > */ > + }; > +} output_flags_t; > + > +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), > OUTPUT_FLAGS_SIZE_ERROR); > + > +/** > + * Internal Packet header > + */ > +typedef struct { > + /* common buffer header */ > + odp_buffer_hdr_t buf_hdr; > + > + input_flags_t input_flags; > + error_flags_t error_flags; > + output_flags_t output_flags; > + > + uint32_t frame_offset; /**< offset to start of frame, even on > error */ > + uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */ > + uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */ > + uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also > ICMP) */ > + > + uint32_t frame_len; > + > + odp_pktio_t input; > + > + uint32_t pad; > + uint8_t payload[]; > + > +} odp_packet_hdr_t; > + > +/** > + * Return the packet header > + */ > +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt) > +{ > + return (odp_packet_hdr_t *)pkt; > +} > + > +/** > + * Parse packet and set internal metadata > + */ > +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > + > diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h > b/platform/linux-dpdk/include/odp_packet_io_internal.h > new file mode 100644 > index 0000000..5948063 > --- /dev/null > +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h > @@ -0,0 +1,52 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > + > +/** > + * @file > + * > + * ODP packet IO - implementation internal > + */ > + > +#ifndef ODP_PACKET_IO_INTERNAL_H_ > +#define ODP_PACKET_IO_INTERNAL_H_ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include <odp_spinlock.h> > +#include <odp_packet_socket.h> > +#ifdef ODP_HAVE_NETMAP > +#include <odp_packet_netmap.h> > +#endif > +#include <odp_packet_dpdk.h> > + > +struct pktio_entry { > + odp_spinlock_t lock; /**< entry spinlock */ > + int taken; /**< is entry taken(1) or free(0) > */ > + odp_queue_t inq_default; /**< default input queue, if set */ > + odp_queue_t outq_default; /**< default out queue */ > + odp_pktio_params_t params; /**< pktio parameters */ > + pkt_sock_t pkt_sock; /**< using socket API for IO */ > + pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap API for IO > */ > +#ifdef ODP_HAVE_NETMAP > + pkt_netmap_t pkt_nm; /**< using netmap API for IO */ > +#endif > + pkt_dpdk_t pkt_dpdk; /**< using DPDK API for IO */ > +}; > + > +typedef union { > + struct pktio_entry s; > + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct > pktio_entry))]; > +} pktio_entry_t; > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif > + > diff --git a/platform/linux-dpdk/source/odp_buffer.c > b/platform/linux-dpdk/source/odp_buffer.c > new file mode 100644 > index 0000000..bfb5ff6 > --- /dev/null > +++ b/platform/linux-dpdk/source/odp_buffer.c > @@ -0,0 +1,102 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include <odp_buffer.h> > +#include <odp_buffer_internal.h> > +#include <odp_buffer_pool_internal.h> > + > +#include <string.h> > +#include <stdio.h> > + > + > +void *odp_buffer_addr(odp_buffer_t buf) > +{ > + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); > + > + return hdr->buf_addr; > +} > + > + > +size_t odp_buffer_size(odp_buffer_t buf) > +{ > + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); > + > + return hdr->buf_len; > +} > + > + > +int odp_buffer_type(odp_buffer_t buf) > +{ > + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); > + > + return hdr->type; > +} > + > + > +int odp_buffer_is_scatter(odp_buffer_t buf) > +{ > + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); > + > + if (hdr->refcnt == 0) > + return 0; > + else > + return 1; > +} > + > + > +int odp_buffer_is_valid(odp_buffer_t buf) > +{ > + odp_buffer_bits_t handle; > + > + handle.u32 = buf; > + > + return (handle.index != ODP_BUFFER_INVALID_INDEX); > +} > + > + > +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf) > +{ > + odp_buffer_hdr_t *hdr; > + int len = 0; > + > + if (!odp_buffer_is_valid(buf)) { > + printf("Buffer is not valid.\n"); > + return len; > + } > + > + hdr = odp_buf_to_hdr(buf); > + > + len += snprintf(&str[len], n-len, > + "Buffer\n"); > + len += snprintf(&str[len], n-len, > + " pool %"PRIu64"\n", (int64_t) hdr->pool); > + len += snprintf(&str[len], n-len, > + " phy_addr %"PRIu64"\n", hdr->buf_physaddr); > + len += snprintf(&str[len], n-len, > + " addr %p\n", hdr->buf_addr); > + len += snprintf(&str[len], n-len, > + " size %u\n", hdr->buf_len); > + len += snprintf(&str[len], n-len, > + " ref_count %i\n", hdr->refcnt); > + len += snprintf(&str[len], n-len, > + " type %i\n", hdr->type); > + > + return len; > +} > + > + > +void odp_buffer_print(odp_buffer_t buf) > +{ > + int max_len = 512; > + char str[max_len]; > + int len; > + > + len = odp_buffer_snprint(str, max_len-1, buf); > + str[len] = 0; > + > + printf("\n%s\n", str); > +} > + > diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c > b/platform/linux-dpdk/source/odp_buffer_pool.c > new file mode 100644 > index 0000000..de90275 > --- /dev/null > +++ b/platform/linux-dpdk/source/odp_buffer_pool.c > @@ -0,0 +1,156 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include <odp_std_types.h> > +#include <odp_buffer_pool.h> > +#include <odp_buffer_pool_internal.h> > +#include <odp_buffer_internal.h> > +#include <odp_packet_internal.h> > +#include <odp_shared_memory.h> > +#include <odp_align.h> > +#include <odp_internal.h> > +#include <odp_config.h> > +#include <odp_hints.h> > +#include <odp_debug.h> > + > +#include <string.h> > +#include <stdlib.h> > + > +/* for DPDK */ > +#include <odp_packet_dpdk.h> > + > +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) > +#define NB_MBUF 8192 > + > +#ifdef POOL_USE_TICKETLOCK > +#include <odp_ticketlock.h> > +#define LOCK(a) odp_ticketlock_lock(a) > +#define UNLOCK(a) odp_ticketlock_unlock(a) > +#define LOCK_INIT(a) odp_ticketlock_init(a) > +#else > +#include <odp_spinlock.h> > +#define LOCK(a) odp_spinlock_lock(a) > +#define UNLOCK(a) odp_spinlock_unlock(a) > +#define LOCK_INIT(a) odp_spinlock_init(a) > +#endif > + > + > +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS > +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS > +#endif > + > +#define NULL_INDEX ((uint32_t)-1) > + > + > +typedef union pool_entry_u { > + struct pool_entry_s s; > + > + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct > pool_entry_s))]; > + > +} pool_entry_t; > + > + > +typedef struct pool_table_t { > + pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS]; > + > +} pool_table_t; > + > + > +/* The pool table */ > +static pool_table_t *pool_tbl; > + > +/* Pool entry pointers (for inlining) */ > +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS]; > + > + > +int odp_buffer_pool_init_global(void) > +{ > + odp_buffer_pool_t i; > + > + pool_tbl = odp_shm_reserve("odp_buffer_pools", > + sizeof(pool_table_t), > + sizeof(pool_entry_t)); > + > + if (pool_tbl == NULL) > + return -1; > + > + memset(pool_tbl, 0, sizeof(pool_table_t)); > + > + > + for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) { > + /* init locks */ > + pool_entry_t *pool = &pool_tbl->pool[i]; > + LOCK_INIT(&pool->s.lock); > + pool->s.pool = i; > + > + pool_entry_ptr[i] = pool; > + } > + > + ODP_DBG("\nBuffer pool init global\n"); > + ODP_DBG(" pool_entry_s size %zu\n", sizeof(struct > pool_entry_s)); > + ODP_DBG(" pool_entry_t size %zu\n", sizeof(pool_entry_t)); > + ODP_DBG(" odp_buffer_hdr_t size %zu\n", sizeof(odp_buffer_hdr_t)); > + ODP_DBG("\n"); > + > + return 0; > +} > + > + > +odp_buffer_pool_t odp_buffer_pool_create(const char *name, > + void *base_addr, uint64_t size, > + size_t buf_size, size_t buf_align, > + int buf_type) > +{ > + struct rte_mempool *pktmbuf_pool = NULL; > + ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n", name, > + (uint64_t) base_addr, (unsigned) size, > + (unsigned) buf_size, (unsigned) buf_align, > + buf_type); > + > + pktmbuf_pool = > + rte_mempool_create(name, NB_MBUF, > + MBUF_SIZE, 32, > + sizeof(struct rte_pktmbuf_pool_private), > + rte_pktmbuf_pool_init, NULL, > + rte_pktmbuf_init, NULL, > + rte_socket_id(), 0); > + if (pktmbuf_pool == NULL) { > + ODP_ERR("Cannot init DPDK mbuf pool\n"); > + return -1; > + } > + > + return (odp_buffer_pool_t) pktmbuf_pool; > +} > + > + > +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name) > +{ > + struct rte_mempool *mp = NULL; > + > + mp = rte_mempool_lookup(name); > + if (mp == NULL) > + return ODP_BUFFER_POOL_INVALID; > + > + return (odp_buffer_pool_t)mp; > +} > + > + > +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id) > +{ > + return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool > *)pool_id); > +} > + > + > +void odp_buffer_free(odp_buffer_t buf) > +{ > + rte_pktmbuf_free((struct rte_mbuf *)buf); > +} > + > + > +void odp_buffer_pool_print(odp_buffer_pool_t pool_id) > +{ > + rte_mempool_dump((const struct rte_mempool *)pool_id); > +} > diff --git a/platform/linux-dpdk/source/odp_init.c > b/platform/linux-dpdk/source/odp_init.c > new file mode 100644 > index 0000000..ecc2066 > --- /dev/null > +++ b/platform/linux-dpdk/source/odp_init.c > @@ -0,0 +1,113 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include <odp_init.h> > +#include <odp_internal.h> > +#include <odp_debug.h> > +#include <odp_packet_dpdk.h> > + > +int odp_init_dpdk(void) > +{ > + int test_argc = 5; > + char *test_argv[6]; > + int core_count, i, num_cores = 0; > + char core_mask[8]; > + > + core_count = odp_sys_core_count(); > + for (i = 0; i < core_count; i++) > + num_cores += (0x1 << i); > + sprintf(core_mask, "%x", num_cores); > + > + test_argv[0] = malloc(sizeof("odp_dpdk")); > + strcpy(test_argv[0], "odp_dpdk"); > + test_argv[1] = malloc(sizeof("-c")); > + strcpy(test_argv[1], "-c"); > + test_argv[2] = malloc(sizeof(core_mask)); > + strcpy(test_argv[2], core_mask); > + test_argv[3] = malloc(sizeof("-n")); > + strcpy(test_argv[3], "-n"); > + test_argv[4] = malloc(sizeof("3")); > + strcpy(test_argv[4], "3"); > + > + if (rte_eal_init(test_argc, (char **)test_argv) < 0) { > + ODP_ERR("Cannot init the Intel DPDK EAL!"); > + return -1; > + } > + > + if (rte_pmd_init_all() < 0) { > + ODP_ERR("Cannot init pmd\n"); > + return -1; > + } > + > + if (rte_eal_pci_probe() < 0) { > + ODP_ERR("Cannot probe PCI\n"); > + return -1; > + } > + > + return 0; > +} > + > +int odp_init_global(void) > +{ > + odp_thread_init_global(); > + > + odp_system_info_init(); > + > + if (odp_init_dpdk()) { > + ODP_ERR("ODP dpdk init failed.\n"); > + return -1; > + } > + > + if (odp_shm_init_global()) { > + ODP_ERR("ODP shm init failed.\n"); > + return -1; > + } > + > + if (odp_buffer_pool_init_global()) { > + ODP_ERR("ODP buffer pool init failed.\n"); > + return -1; > + } > + > + if (odp_queue_init_global()) { > + ODP_ERR("ODP queue init failed.\n"); > + return -1; > + } > + > + if (odp_schedule_init_global()) { > + ODP_ERR("ODP schedule init failed.\n"); > + return -1; > + } > + > + if (odp_pktio_init_global()) { > + ODP_ERR("ODP packet io init failed.\n"); > + return -1; > + } > + > + if (odp_timer_init_global()) { > + ODP_ERR("ODP timer init failed.\n"); > + return -1; > + } > + > + return 0; > +} > + > + > +int odp_init_local(int thr_id) > +{ > + odp_thread_init_local(thr_id); > + > + if (odp_pktio_init_local()) { > + ODP_ERR("ODP packet io local init failed.\n"); > + return -1; > + } > + > + if (odp_schedule_init_local()) { > + ODP_ERR("ODP schedule local init failed.\n"); > + return -1; > + } > + > + return 0; > +} > diff --git a/platform/linux-dpdk/source/odp_packet.c > b/platform/linux-dpdk/source/odp_packet.c > new file mode 100644 > index 0000000..c34e626 > --- /dev/null > +++ b/platform/linux-dpdk/source/odp_packet.c > @@ -0,0 +1,374 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include <odp_packet.h> > +#include <odp_packet_internal.h> > +#include <odp_hints.h> > +#include <odp_byteorder.h> > + > +#include <helper/odp_eth.h> > +#include <helper/odp_ip.h> > + > +#include <string.h> > +#include <stdio.h> > + > +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, odp_ipv4hdr_t > *ipv4, > + size_t *offset_out); > +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, odp_ipv6hdr_t > *ipv6, > + size_t *offset_out); > + > +void odp_packet_init(odp_packet_t pkt) > +{ > + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); > + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, > buf_hdr); > + uint8_t *start; > + size_t len; > + > + start = (uint8_t *)pkt_hdr + start_offset; > + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; > + memset(start, 0, len); > + > + pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; > + pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; > + pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; > +} > + > +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf) > +{ > + return (odp_packet_t)buf; > +} > + > +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt) > +{ > + return (odp_buffer_t)pkt; > +} > + > +void odp_packet_set_len(odp_packet_t pkt, size_t len) > +{ > + /* for rte_pktmbuf */ > + odp_buffer_hdr_t *buf_hdr = > odp_buf_to_hdr(odp_buffer_from_packet(pkt)); > + buf_hdr->pkt.data_len = len; > + > + odp_packet_hdr(pkt)->frame_len = len; > +} > + > +size_t odp_packet_get_len(odp_packet_t pkt) > +{ > + return odp_packet_hdr(pkt)->frame_len; > +} > + > +uint8_t *odp_packet_buf_addr(odp_packet_t pkt) > +{ > + return odp_buffer_addr(odp_buffer_from_packet(pkt)); > +} > + > +uint8_t *odp_packet_start(odp_packet_t pkt) > +{ > + return odp_packet_buf_addr(pkt) + > odp_packet_hdr(pkt)->frame_offset; > +} > + > + > +uint8_t *odp_packet_l2(odp_packet_t pkt) > +{ > + const size_t offset = odp_packet_l2_offset(pkt); > + > + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) > + return NULL; > + > + return odp_packet_buf_addr(pkt) + offset; > +} > + > +size_t odp_packet_l2_offset(odp_packet_t pkt) > +{ > + return odp_packet_hdr(pkt)->l2_offset; > +} > + > +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset) > +{ > + odp_packet_hdr(pkt)->l2_offset = offset; > +} > + > +uint8_t *odp_packet_l3(odp_packet_t pkt) > +{ > + const size_t offset = odp_packet_l3_offset(pkt); > + > + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) > + return NULL; > + > + return odp_packet_buf_addr(pkt) + offset; > +} > + > +size_t odp_packet_l3_offset(odp_packet_t pkt) > +{ > + return odp_packet_hdr(pkt)->l3_offset; > +} > + > +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset) > +{ > + odp_packet_hdr(pkt)->l3_offset = offset; > +} > + > +uint8_t *odp_packet_l4(odp_packet_t pkt) > +{ > + const size_t offset = odp_packet_l4_offset(pkt); > + > + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) > + return NULL; > + > + return odp_packet_buf_addr(pkt) + offset; > +} > + > +size_t odp_packet_l4_offset(odp_packet_t pkt) > +{ > + return odp_packet_hdr(pkt)->l4_offset; > +} > + > +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset) > +{ > + odp_packet_hdr(pkt)->l4_offset = offset; > +} > + > +/** > + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP > + * > + * Internal function: caller is resposible for passing only valid packet > handles > + * , lengths and offsets (usually done&called in packet input). > + * > + * @param pkt Packet handle > + * @param len Packet length in bytes > + * @param frame_offset Byte offset to L2 header > + */ > +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset) > +{ > + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); > + odp_ethhdr_t *eth; > + odp_vlanhdr_t *vlan; > + odp_ipv4hdr_t *ipv4; > + odp_ipv6hdr_t *ipv6; > + uint16_t ethtype; > + size_t offset = 0; > + uint8_t ip_proto = 0; > + > + pkt_hdr->input_flags.eth = 1; > + pkt_hdr->frame_offset = frame_offset; > + pkt_hdr->frame_len = len; > + > + if (odp_unlikely(len < ODP_ETH_LEN_MIN)) { > + pkt_hdr->error_flags.frame_len = 1; > + return; > + } else if (len > ODP_ETH_LEN_MAX) { > + pkt_hdr->input_flags.jumbo = 1; > + } > + > + /* Assume valid L2 header, no CRC/FCS check in SW */ > + pkt_hdr->input_flags.l2 = 1; > + pkt_hdr->l2_offset = frame_offset; > + > + eth = (odp_ethhdr_t *)odp_packet_start(pkt); > + ethtype = odp_be_to_cpu_16(eth->type); > + vlan = (odp_vlanhdr_t *)ð->type; > + > + if (ethtype == ODP_ETHTYPE_VLAN_OUTER) { > + pkt_hdr->input_flags.vlan_qinq = 1; > + ethtype = odp_be_to_cpu_16(vlan->tpid); > + offset += sizeof(odp_vlanhdr_t); > + vlan = &vlan[1]; > + } > + > + if (ethtype == ODP_ETHTYPE_VLAN) { > + pkt_hdr->input_flags.vlan = 1; > + ethtype = odp_be_to_cpu_16(vlan->tpid); > + offset += sizeof(odp_vlanhdr_t); > + } > + > + /* Set l3_offset+flag only for known ethtypes */ > + switch (ethtype) { > + case ODP_ETHTYPE_IPV4: > + pkt_hdr->input_flags.ipv4 = 1; > + pkt_hdr->input_flags.l3 = 1; > + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + > offset; > + ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt); > + ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset); > + break; > + case ODP_ETHTYPE_IPV6: > + pkt_hdr->input_flags.ipv6 = 1; > + pkt_hdr->input_flags.l3 = 1; > + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + > offset; > + ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt); > + ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset); > + break; > + case ODP_ETHTYPE_ARP: > + pkt_hdr->input_flags.arp = 1; > + /* fall through */ > + default: > + ip_proto = 0; > + break; > + } > + > + switch (ip_proto) { > + case ODP_IPPROTO_UDP: > + pkt_hdr->input_flags.udp = 1; > + pkt_hdr->input_flags.l4 = 1; > + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; > + break; > + case ODP_IPPROTO_TCP: > + pkt_hdr->input_flags.tcp = 1; > + pkt_hdr->input_flags.l4 = 1; > + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; > + break; > + case ODP_IPPROTO_SCTP: > + pkt_hdr->input_flags.sctp = 1; > + pkt_hdr->input_flags.l4 = 1; > + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; > + break; > + case ODP_IPPROTO_ICMP: > + pkt_hdr->input_flags.icmp = 1; > + pkt_hdr->input_flags.l4 = 1; > + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; > + break; > + default: > + /* 0 or unhandled IP protocols, don't set L4 flag+offset */ > + if (pkt_hdr->input_flags.ipv6) { > + /* IPv6 next_hdr is not L4, mark as IP-option > instead */ > + pkt_hdr->input_flags.ipopt = 1; > + } > + break; > + } > +} > + > +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, odp_ipv4hdr_t > *ipv4, > + size_t *offset_out) > +{ > + uint8_t ihl; > + uint16_t frag_offset; > + > + ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl); > + if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) { > + pkt_hdr->error_flags.ip_err = 1; > + return 0; > + } > + > + if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) { > + pkt_hdr->input_flags.ipopt = 1; > + return 0; > + } > + > + /* A packet is a fragment if: > + * "more fragments" flag is set (all fragments except the last) > + * OR > + * "fragment offset" field is nonzero (all fragments except the > first) > + */ > + frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); > + if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) { > + pkt_hdr->input_flags.ipfrag = 1; > + return 0; > + } > + > + if (ipv4->proto == ODP_IPPROTO_ESP || > + ipv4->proto == ODP_IPPROTO_AH) { > + pkt_hdr->input_flags.ipsec = 1; > + return 0; > + } > + > + /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after > return */ > + > + *offset_out = sizeof(uint32_t) * ihl; > + return ipv4->proto; > +} > + > +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, odp_ipv6hdr_t > *ipv6, > + size_t *offset_out) > +{ > + if (ipv6->next_hdr == ODP_IPPROTO_ESP || > + ipv6->next_hdr == ODP_IPPROTO_AH) { > + pkt_hdr->input_flags.ipopt = 1; > + pkt_hdr->input_flags.ipsec = 1; > + return 0; > + } > + > + if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) { > + pkt_hdr->input_flags.ipopt = 1; > + pkt_hdr->input_flags.ipfrag = 1; > + return 0; > + } > + > + /* Don't step through more extensions */ > + *offset_out = ODP_IPV6HDR_LEN; > + return ipv6->next_hdr; > +} > + > +void odp_packet_print(odp_packet_t pkt) > +{ > + int max_len = 512; > + char str[max_len]; > + int len = 0; > + int n = max_len-1; > + odp_packet_hdr_t *hdr = odp_packet_hdr(pkt); > + > + len += snprintf(&str[len], n-len, "Packet "); > + len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt); > + len += snprintf(&str[len], n-len, > + " input_flags 0x%x\n", hdr->input_flags.all); > + len += snprintf(&str[len], n-len, > + " error_flags 0x%x\n", hdr->error_flags.all); > + len += snprintf(&str[len], n-len, > + " output_flags 0x%x\n", hdr->output_flags.all); > + len += snprintf(&str[len], n-len, > + " frame_offset %u\n", hdr->frame_offset); > + len += snprintf(&str[len], n-len, > + " l2_offset %u\n", hdr->l2_offset); > + len += snprintf(&str[len], n-len, > + " l3_offset %u\n", hdr->l3_offset); > + len += snprintf(&str[len], n-len, > + " l4_offset %u\n", hdr->l4_offset); > + len += snprintf(&str[len], n-len, > + " frame_len %u\n", hdr->frame_len); > + len += snprintf(&str[len], n-len, > + " input %u\n", hdr->input); > + str[len] = '\0'; > + > + printf("\n%s\n", str); > +} > + > +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src) > +{ > + odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst); > + odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src); > + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, > buf_hdr); > + uint8_t *start_src; > + uint8_t *start_dst; > + size_t len; > + > + if (pkt_dst == ODP_PACKET_INVALID || pkt_src == ODP_PACKET_INVALID) > + return -1; > + > + /* if (pkt_hdr_dst->buf_hdr.size < */ > + /* pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */ > + if (pkt_hdr_dst->buf_hdr.buf_len < > + pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) > + return -1; > + > + /* Copy packet header */ > + start_dst = (uint8_t *)pkt_hdr_dst + start_offset; > + start_src = (uint8_t *)pkt_hdr_src + start_offset; > + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; > + memcpy(start_dst, start_src, len); > + > + /* Copy frame payload */ > + start_dst = (uint8_t *)odp_packet_start(pkt_dst); > + start_src = (uint8_t *)odp_packet_start(pkt_src); > + len = pkt_hdr_src->frame_len; > + memcpy(start_dst, start_src, len); > + > + /* Copy useful things from the buffer header */ > + /* pkt_hdr_dst->buf_hdr.cur_offset = > pkt_hdr_src->buf_hdr.cur_offset; */ > + > + /* Create a copy of the scatter list */ > + /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */ > + /* odp_buffer_from_packet(pkt_src)); */ > + > + return 0; > +} > diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c > b/platform/linux-dpdk/source/odp_packet_dpdk.c > new file mode 100644 > index 0000000..6d16bbe > --- /dev/null > +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c > @@ -0,0 +1,177 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#define _GNU_SOURCE > +#include <stdio.h> > +#include <errno.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <sys/ioctl.h> > +#include <sys/mman.h> > +#include <poll.h> > +#include <unistd.h> > +#include <fcntl.h> > +#include <string.h> > +#include <stdlib.h> > + > +#include <linux/ethtool.h> > +#include <linux/sockios.h> > + > +#include <odp_hints.h> > +#include <odp_thread.h> > + > +#include <odp_packet_dpdk.h> > +#include <net/if.h> > + > +/* > + * RX and TX Prefetch, Host, and Write-back threshold values should be > + * carefully set for optimal performance. Consult the network > + * controller's datasheet and supporting DPDK documentation for guidance > + * on how these parameters should be set. > + */ > +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ > +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ > +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. > */ > + > +/* > + * These default values are optimized for use with the Intel(R) 82599 10 > GbE > + * Controller and the DPDK ixgbe PMD. Consider using other values for > other > + * network controllers and/or network drivers. > + */ > +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */ > +#define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ > +#define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. > */ > + > +#define MAX_PKT_BURST 32 > +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ > +#define RTE_TEST_RX_DESC_DEFAULT 128 > +#define RTE_TEST_TX_DESC_DEFAULT 512 > +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; > +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; > + > +static const struct rte_eth_conf port_conf = { > + .rxmode = { > + .split_hdr_size = 0, > + .header_split = 0, /**< Header Split disabled */ > + .hw_ip_checksum = 0, /**< IP checksum offload disabled */ > + .hw_vlan_filter = 0, /**< VLAN filtering disabled */ > + .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ > + .hw_strip_crc = 0, /**< CRC stripped by hardware */ > + }, > + .txmode = { > + .mq_mode = ETH_MQ_TX_NONE, > + }, > +}; > + > +static const struct rte_eth_rxconf rx_conf = { > + .rx_thresh = { > + .pthresh = RX_PTHRESH, > + .hthresh = RX_HTHRESH, > + .wthresh = RX_WTHRESH, > + }, > +}; > + > +static const struct rte_eth_txconf tx_conf = { > + .tx_thresh = { > + .pthresh = TX_PTHRESH, > + .hthresh = TX_HTHRESH, > + .wthresh = TX_WTHRESH, > + }, > + .tx_free_thresh = 0, /* Use PMD default values */ > + .tx_rs_thresh = 0, /* Use PMD default values */ > + /* > + * As the example won't handle mult-segments and offload cases, > + * set the flag by default. > + */ > + .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, > +}; > + > +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, > + odp_buffer_pool_t pool) > +{ > + ODP_DBG("setup_pkt_dpdk\n"); > + > + static struct ether_addr eth_addr[RTE_MAX_ETHPORTS]; > + uint8_t portid = 0; > + uint16_t queueid = 0; > + int ret; > + printf("vincent netdev: %s\n", netdev); > + printf("vincent pool: %lx\n", pool); > + > + portid = atoi(netdev); > + pkt_dpdk->portid = portid; > + pkt_dpdk->queueid = queueid; > + pkt_dpdk->pool = pool; > + printf("vincent portid: %u\n", portid); > + > + fflush(stdout); > + ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); > + if (ret < 0) > + ODP_ERR("Cannot configure device: err=%d, port=%u\n", > + ret, (unsigned) portid); > + > + rte_eth_macaddr_get(portid, ð_addr[portid]); > + ODP_DBG("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", > + (unsigned) portid, > + eth_addr[portid].addr_bytes[0], > + eth_addr[portid].addr_bytes[1], > + eth_addr[portid].addr_bytes[2], > + eth_addr[portid].addr_bytes[3], > + eth_addr[portid].addr_bytes[4], > + eth_addr[portid].addr_bytes[5]); > + > + /* init one RX queue on each port */ > + fflush(stdout); > + ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, > + rte_eth_dev_socket_id(portid), > &rx_conf, > + (struct rte_mempool *)pool); > + if (ret < 0) > + ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n", > + ret, (unsigned) portid); > + ODP_DBG("dpdk rx queue setup done\n"); > + > + /* init one TX queue on each port */ > + fflush(stdout); > + ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, > + rte_eth_dev_socket_id(portid), &tx_conf); > + if (ret < 0) > + ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n", > + ret, (unsigned) portid); > + ODP_DBG("dpdk tx queue setup done\n"); > + > + /* Start device */ > + ret = rte_eth_dev_start(portid); > + if (ret < 0) > + ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n", > + ret, (unsigned) portid); > + ODP_DBG("dpdk setup done\n\n"); > + > + > + return 0; > +} > + > +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk) > +{ > + ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid); > + > + return 0; > +} > + > +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], > + unsigned len) > +{ > + return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid, > + (uint16_t)pkt_dpdk->queueid, > + (struct rte_mbuf **)pkt_table, > (uint16_t)len); > +} > + > +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], > + unsigned len) > +{ > + return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid, > + (uint16_t)pkt_dpdk->queueid, > + (struct rte_mbuf **)pkt_table, > (uint16_t)len); > +} > diff --git a/platform/linux-dpdk/source/odp_packet_io.c > b/platform/linux-dpdk/source/odp_packet_io.c > new file mode 100644 > index 0000000..abea0ec > --- /dev/null > +++ b/platform/linux-dpdk/source/odp_packet_io.c > @@ -0,0 +1,561 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include <odp_packet_io.h> > +#include <odp_packet_io_internal.h> > +#include <odp_packet_io_queue.h> > +#include <odp_packet.h> > +#include <odp_packet_internal.h> > +#include <odp_internal.h> > +#include <odp_spinlock.h> > +#include <odp_shared_memory.h> > +#include <odp_packet_socket.h> > +#ifdef ODP_HAVE_NETMAP > +#include <odp_packet_netmap.h> > +#endif > +#include <odp_hints.h> > +#include <odp_config.h> > +#include <odp_queue_internal.h> > +#include <odp_schedule_internal.h> > +#include <odp_debug.h> > + > +#include <odp_pktio_socket.h> > +#ifdef ODP_HAVE_NETMAP > +#include <odp_pktio_netmap.h> > +#endif > + > +#include <string.h> > + > +typedef struct { > + pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES]; > +} pktio_table_t; > + > +static pktio_table_t *pktio_tbl; > + > + > +static pktio_entry_t *get_entry(odp_pktio_t id) > +{ > + if (odp_unlikely(id == ODP_PKTIO_INVALID || > + id > ODP_CONFIG_PKTIO_ENTRIES)) > + return NULL; > + > + return &pktio_tbl->entries[id - 1]; > +} > + > +int odp_pktio_init_global(void) > +{ > + char name[ODP_QUEUE_NAME_LEN]; > + pktio_entry_t *pktio_entry; > + queue_entry_t *queue_entry; > + odp_queue_t qid; > + int id; > + > + pktio_tbl = odp_shm_reserve("odp_pktio_entries", > + sizeof(pktio_table_t), > + sizeof(pktio_entry_t)); > + if (pktio_tbl == NULL) > + return -1; > + > + memset(pktio_tbl, 0, sizeof(pktio_table_t)); > + > + for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) { > + pktio_entry = get_entry(id); > + > + odp_spinlock_init(&pktio_entry->s.lock); > + > + /* Create a default output queue for each pktio resource */ > + snprintf(name, sizeof(name), "%i-pktio_outq_default", > (int)id); > + name[ODP_QUEUE_NAME_LEN-1] = '\0'; > + > + qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, NULL); > + if (qid == ODP_QUEUE_INVALID) > + return -1; > + pktio_entry->s.outq_default = qid; > + > + queue_entry = queue_to_qentry(qid); > + queue_entry->s.pktout = id; > + } > + > + return 0; > +} > + > +int odp_pktio_init_local(void) > +{ > + return 0; > +} > + > +static int is_free(pktio_entry_t *entry) > +{ > + return (entry->s.taken == 0); > +} > + > +static void set_free(pktio_entry_t *entry) > +{ > + entry->s.taken = 0; > +} > + > +static void set_taken(pktio_entry_t *entry) > +{ > + entry->s.taken = 1; > +} > + > +static void lock_entry(pktio_entry_t *entry) > +{ > + odp_spinlock_lock(&entry->s.lock); > +} > + > +static void unlock_entry(pktio_entry_t *entry) > +{ > + odp_spinlock_unlock(&entry->s.lock); > +} > + > +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t > *params) > +{ > + set_taken(entry); > + entry->s.inq_default = ODP_QUEUE_INVALID; > + switch (params->type) { > + case ODP_PKTIO_TYPE_SOCKET_BASIC: > + case ODP_PKTIO_TYPE_SOCKET_MMSG: > + case ODP_PKTIO_TYPE_SOCKET_MMAP: > + memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock)); > + memset(&entry->s.pkt_sock_mmap, 0, > + sizeof(entry->s.pkt_sock_mmap)); > + break; > +#ifdef ODP_HAVE_NETMAP > + case ODP_PKTIO_TYPE_NETMAP: > + memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm)); > + break; > +#endif > + case ODP_PKTIO_TYPE_DPDK: > + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); > + break; > + default: > + ODP_ERR("Packet I/O type not supported. Please > recompile\n"); > + break; > + } > + /* Save pktio parameters, type is the most useful */ > + memcpy(&entry->s.params, params, sizeof(*params)); > +} > + > +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params) > +{ > + odp_pktio_t id; > + pktio_entry_t *entry; > + int i; > + > + for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) { > + entry = &pktio_tbl->entries[i]; > + if (is_free(entry)) { > + lock_entry(entry); > + if (is_free(entry)) { > + init_pktio_entry(entry, params); > + id = i + 1; > + return id; /* return with entry locked! */ > + } > + unlock_entry(entry); > + } > + } > + > + return ODP_PKTIO_INVALID; > +} > + > +static int free_pktio_entry(odp_pktio_t id) > +{ > + pktio_entry_t *entry = get_entry(id); > + > + if (entry == NULL) > + return -1; > + > + set_free(entry); > + > + return 0; > +} > + > +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool, > + odp_pktio_params_t *params) > +{ > + odp_pktio_t id; > + pktio_entry_t *pktio_entry; > + int res; > + > + if (params == NULL) { > + ODP_ERR("Invalid pktio params\n"); > + return ODP_PKTIO_INVALID; > + } > + > + switch (params->type) { > + case ODP_PKTIO_TYPE_SOCKET_BASIC: > + case ODP_PKTIO_TYPE_SOCKET_MMSG: > + case ODP_PKTIO_TYPE_SOCKET_MMAP: > + ODP_DBG("Allocating socket pktio\n"); > + break; > +#ifdef ODP_HAVE_NETMAP > + case ODP_PKTIO_TYPE_NETMAP: > + ODP_DBG("Allocating netmap pktio\n"); > + break; > +#endif > + case ODP_PKTIO_TYPE_DPDK: > + ODP_DBG("Allocating dpdk pktio\n"); > + break; > + default: > + ODP_ERR("Invalid pktio type: %02x\n", params->type); > + return ODP_PKTIO_INVALID; > + } > + > + id = alloc_lock_pktio_entry(params); > + if (id == ODP_PKTIO_INVALID) { > + ODP_ERR("No resources available.\n"); > + return ODP_PKTIO_INVALID; > + } > + /* if successful, alloc_pktio_entry() returns with the entry > locked */ > + > + pktio_entry = get_entry(id); > + > + switch (params->type) { > + case ODP_PKTIO_TYPE_SOCKET_BASIC: > + case ODP_PKTIO_TYPE_SOCKET_MMSG: > + res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, pool); > + if (res == -1) { > + close_pkt_sock(&pktio_entry->s.pkt_sock); > + free_pktio_entry(id); > + id = ODP_PKTIO_INVALID; > + } > + break; > + case ODP_PKTIO_TYPE_SOCKET_MMAP: > + res = setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, > dev, > + pool, params->sock_params.fanout); > + if (res == -1) { > + close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap); > + free_pktio_entry(id); > + id = ODP_PKTIO_INVALID; > + } > + break; > +#ifdef ODP_HAVE_NETMAP > + case ODP_PKTIO_TYPE_NETMAP: > + > + res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev, > + pool, ¶ms->nm_params); > + if (res == -1) { > + close_pkt_netmap(&pktio_entry->s.pkt_nm); > + free_pktio_entry(id); > + id = ODP_PKTIO_INVALID; > + } > + break; > +#endif > + case ODP_PKTIO_TYPE_DPDK: > + res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, pool); > + if (res == -1) { > + close_pkt_dpdk(&pktio_entry->s.pkt_dpdk); > + free_pktio_entry(id); > + id = ODP_PKTIO_INVALID; > + } > + break; > + default: > + free_pktio_entry(id); > + id = ODP_PKTIO_INVALID; > + ODP_ERR("Invalid pktio type. Please recompile.\n"); > + break; > + } > + > + unlock_entry(pktio_entry); > + return id; > +} > + > +int odp_pktio_close(odp_pktio_t id) > +{ > + pktio_entry_t *entry; > + int res = -1; > + > + entry = get_entry(id); > + if (entry == NULL) > + return -1; > + > + lock_entry(entry); > + if (!is_free(entry)) { > + switch (entry->s.params.type) { > + case ODP_PKTIO_TYPE_SOCKET_BASIC: > + case ODP_PKTIO_TYPE_SOCKET_MMSG: > + res = close_pkt_sock(&entry->s.pkt_sock); > + break; > + case ODP_PKTIO_TYPE_SOCKET_MMAP: > + res = > close_pkt_sock_mmap(&entry->s.pkt_sock_mmap); > + break; > +#ifdef ODP_HAVE_NETMAP > + case ODP_PKTIO_TYPE_NETMAP: > + res = close_pkt_netmap(&entry->s.pkt_nm); > + break; > +#endif > + case ODP_PKTIO_TYPE_DPDK: > + res = close_pkt_dpdk(&entry->s.pkt_dpdk); > + break; > + default: > + break; > + res |= free_pktio_entry(id); > + } > + } > + unlock_entry(entry); > + > + if (res != 0) > + return -1; > + > + return 0; > +} > + > +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio) > +{ > + odp_packet_hdr(pkt)->input = pktio; > +} > + > +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt) > +{ > + return odp_packet_hdr(pkt)->input; > +} > + > +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len) > +{ > + pktio_entry_t *pktio_entry = get_entry(id); > + int pkts; > + int i; > + > + if (pktio_entry == NULL) > + return -1; > + > + lock_entry(pktio_entry); > + switch (pktio_entry->s.params.type) { > + case ODP_PKTIO_TYPE_SOCKET_BASIC: > + pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock, > + pkt_table, len); > + break; > + case ODP_PKTIO_TYPE_SOCKET_MMSG: > + pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, > + pkt_table, len); > + break; > + case ODP_PKTIO_TYPE_SOCKET_MMAP: > + pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, > + pkt_table, len); > + break; > +#ifdef ODP_HAVE_NETMAP > + case ODP_PKTIO_TYPE_NETMAP: > + pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm, pkt_table, > len); > + break; > +#endif > + case ODP_PKTIO_TYPE_DPDK: > + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, > len); > + break; > + default: > + pkts = -1; > + break; > + } > + > + unlock_entry(pktio_entry); > + if (pkts < 0) > + return pkts; > + > + for (i = 0; i < pkts; ++i) > + odp_pktio_set_input(pkt_table[i], id); > + > + return pkts; > +} > + > +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len) > +{ > + pktio_entry_t *pktio_entry = get_entry(id); > + int pkts; > + > + if (pktio_entry == NULL) > + return -1; > + > + lock_entry(pktio_entry); > + switch (pktio_entry->s.params.type) { > + case ODP_PKTIO_TYPE_SOCKET_BASIC: > + pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock, > + pkt_table, len); > + break; > + case ODP_PKTIO_TYPE_SOCKET_MMSG: > + pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, > + pkt_table, len); > + break; > + case ODP_PKTIO_TYPE_SOCKET_MMAP: > + pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, > + pkt_table, len); > + break; > +#ifdef ODP_HAVE_NETMAP > + case ODP_PKTIO_TYPE_NETMAP: > + pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm, > + pkt_table, len); > + break; > +#endif > + case ODP_PKTIO_TYPE_DPDK: > + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, > + pkt_table, len); > + break; > + default: > + pkts = -1; > + } > + unlock_entry(pktio_entry); > + > + return pkts; > +} > + > +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue) > +{ > + pktio_entry_t *pktio_entry = get_entry(id); > + queue_entry_t *qentry = queue_to_qentry(queue); > + > + if (pktio_entry == NULL || qentry == NULL) > + return -1; > + > + if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN) > + return -1; > + > + lock_entry(pktio_entry); > + pktio_entry->s.inq_default = queue; > + unlock_entry(pktio_entry); > + > + queue_lock(qentry); > + qentry->s.pktin = id; > + qentry->s.status = QUEUE_STATUS_SCHED; > + queue_unlock(qentry); > + > + odp_schedule_queue(queue, qentry->s.param.sched.prio); > + > + return 0; > +} > + > +int odp_pktio_inq_remdef(odp_pktio_t id) > +{ > + return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID); > +} > + > +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id) > +{ > + pktio_entry_t *pktio_entry = get_entry(id); > + > + if (pktio_entry == NULL) > + return ODP_QUEUE_INVALID; > + > + return pktio_entry->s.inq_default; > +} > + > +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id) > +{ > + pktio_entry_t *pktio_entry = get_entry(id); > + > + if (pktio_entry == NULL) > + return ODP_QUEUE_INVALID; > + > + return pktio_entry->s.outq_default; > +} > + > +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) > +{ > + odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t) buf_hdr); > + int len = 1; > + int nbr; > + > + nbr = odp_pktio_send(qentry->s.pktout, &pkt, len); > + return (nbr == len ? 0 : -1); > +} > + > +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry) > +{ > + (void)qentry; > + return NULL; > +} > + > +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], > + int num) > +{ > + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; > + int nbr; > + int i; > + > + for (i = 0; i < num; ++i) > + pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t) > buf_hdr[i]); > + > + nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num); > + return (nbr == num ? 0 : -1); > +} > + > +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], > + int num) > +{ > + (void)qentry; > + (void)buf_hdr; > + (void)num; > + > + return 0; > +} > + > +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) > +{ > + /* Use default action */ > + return queue_enq(qentry, buf_hdr); > +} > + > +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry) > +{ > + odp_buffer_hdr_t *buf_hdr; > + > + buf_hdr = queue_deq(qentry); > + > + if (buf_hdr == NULL) { > + odp_packet_t pkt; > + odp_buffer_t buf; > + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; > + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; > + int pkts, i, j; > + > + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, > + QUEUE_MULTI_MAX); > + > + if (pkts > 0) { > + pkt = pkt_tbl[0]; > + buf = odp_buffer_from_packet(pkt); > + buf_hdr = odp_buf_to_hdr(buf); > + > + for (i = 1, j = 0; i < pkts; ++i) { > + buf = odp_buffer_from_packet(pkt_tbl[i]); > + tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf); > + } > + queue_enq_multi(qentry, tmp_hdr_tbl, j); > + } > + } > + > + return buf_hdr; > +} > + > +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], > int num) > +{ > + /* Use default action */ > + return queue_enq_multi(qentry, buf_hdr, num); > +} > + > +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], > int num) > +{ > + int nbr; > + > + nbr = queue_deq_multi(qentry, buf_hdr, num); > + > + if (nbr < num) { > + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; > + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; > + odp_buffer_t buf; > + int pkts, i; > + > + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, > + QUEUE_MULTI_MAX); > + if (pkts > 0) { > + for (i = 0; i < pkts; ++i) { > + buf = odp_buffer_from_packet(pkt_tbl[i]); > + tmp_hdr_tbl[i] = odp_buf_to_hdr(buf); > + } > + queue_enq_multi(qentry, tmp_hdr_tbl, pkts); > + } > + } > + > + return nbr; > +} > diff --git a/platform/linux-dpdk/source/odp_queue.c > b/platform/linux-dpdk/source/odp_queue.c > new file mode 100644 > index 0000000..554b8ea > --- /dev/null > +++ b/platform/linux-dpdk/source/odp_queue.c > @@ -0,0 +1,435 @@ > +/* Copyright (c) 2013, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include <odp_queue.h> > +#include <odp_queue_internal.h> > +#include <odp_std_types.h> > +#include <odp_align.h> > +#include <odp_buffer.h> > +#include <odp_buffer_internal.h> > +#include <odp_buffer_pool_internal.h> > +#include <odp_internal.h> > +#include <odp_shared_memory.h> > +#include <odp_schedule_internal.h> > +#include <odp_config.h> > +#include <odp_packet_io_internal.h> > +#include <odp_packet_io_queue.h> > +#include <odp_debug.h> > +#include <odp_hints.h> > + > +#ifdef USE_TICKETLOCK > +#include <odp_ticketlock.h> > +#define LOCK(a) odp_ticketlock_lock(a) > +#define UNLOCK(a) odp_ticketlock_unlock(a) > +#define LOCK_INIT(a) odp_ticketlock_init(a) > +#else > +#include <odp_spinlock.h> > +#define LOCK(a) odp_spinlock_lock(a) > +#define UNLOCK(a) odp_spinlock_unlock(a) > +#define LOCK_INIT(a) odp_spinlock_init(a) > +#endif > + > +#include <string.h> > + > + > +typedef struct queue_table_t { > + queue_entry_t queue[ODP_CONFIG_QUEUES]; > +} queue_table_t; > + > +static queue_table_t *queue_tbl; > + > + > +queue_entry_t *get_qentry(uint32_t queue_id) > +{ > + return &queue_tbl->queue[queue_id]; > +} > + > +static void queue_init(queue_entry_t *queue, const char *name, > + odp_queue_type_t type, odp_queue_param_t *param) > +{ > + strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1); > + queue->s.type = type; > + > + if (param) { > + memcpy(&queue->s.param, param, sizeof(odp_queue_param_t)); > + } else { > + /* Defaults */ > + memset(&queue->s.param, 0, sizeof(odp_queue_param_t)); > + queue->s.param.sched.prio = ODP_SCHED_PRIO_DEFAULT; > + queue->s.param.sched.sync = ODP_SCHED_SYNC_DEFAULT; > + queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT; > + } > + > + switch (type) { > + case ODP_QUEUE_TYPE_PKTIN: > + queue->s.enqueue = pktin_enqueue; > + queue->s.dequeue = pktin_dequeue; > + queue->s.enqueue_multi = pktin_enq_multi; > + queue->s.dequeue_multi = pktin_deq_multi; > + break; > + case ODP_QUEUE_TYPE_PKTOUT: > + queue->s.enqueue = pktout_enqueue; > + queue->s.dequeue = pktout_dequeue; > + queue->s.enqueue_multi = pktout_enq_multi; > + queue->s.dequeue_multi = pktout_deq_multi; > + break; > + default: > + queue->s.enqueue = queue_enq; > + queue->s.dequeue = queue_deq; > + queue->s.enqueue_multi = queue_enq_multi; > + queue->s.dequeue_multi = queue_deq_multi; > + break; > + } > + > + queue->s.head = NULL; > + queue->s.tail = NULL; > + queue->s.sched_buf = ODP_BUFFER_INVALID; > +} > + > + > +int odp_queue_init_global(void) > +{ > + uint32_t i; > + > + ODP_DBG("Queue init ... "); > + > + queue_tbl = odp_shm_reserve("odp_queues", > + sizeof(queue_table_t), > + sizeof(queue_entry_t)); > + > + if (queue_tbl == NULL) > + return -1; > + > + memset(queue_tbl, 0, sizeof(queue_table_t)); > + > + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { > + /* init locks */ > + queue_entry_t *queue = get_qentry(i); > + LOCK_INIT(&queue->s.lock); > + queue->s.handle = queue_from_id(i); > + } > + > + ODP_DBG("done\n"); > + ODP_DBG("Queue init global\n"); > + ODP_DBG(" struct queue_entry_s size %zu\n", > + sizeof(struct queue_entry_s)); > + ODP_DBG(" queue_entry_t size %zu\n", > + sizeof(queue_entry_t)); > + ODP_DBG("\n"); > + > + return 0; > +} > + > +odp_queue_type_t odp_queue_type(odp_queue_t handle) > +{ > + queue_entry_t *queue; > + > + queue = queue_to_qentry(handle); > + > + return queue->s.type; > +} > + > +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle) > +{ > + queue_entry_t *queue; > + > + queue = queue_to_qentry(handle); > + > + return queue->s.param.sched.sync; > +} > + > +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type, > + odp_queue_param_t *param) > +{ > + uint32_t i; > + queue_entry_t *queue; > + odp_queue_t handle = ODP_QUEUE_INVALID; > + > + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { > + queue = &queue_tbl->queue[i]; > + > + if (queue->s.status != QUEUE_STATUS_FREE) > + continue; > + > + LOCK(&queue->s.lock); > + if (queue->s.status == QUEUE_STATUS_FREE) { > + queue_init(queue, name, type, param); > + > + if (type == ODP_QUEUE_TYPE_SCHED || > + type == ODP_QUEUE_TYPE_PKTIN) > + queue->s.status = QUEUE_STATUS_NOTSCHED; > + else > + queue->s.status = QUEUE_STATUS_READY; > + > + handle = queue->s.handle; > + UNLOCK(&queue->s.lock); > + break; > + } > + UNLOCK(&queue->s.lock); > + } > + > + if (handle != ODP_QUEUE_INVALID && > + (type == ODP_QUEUE_TYPE_SCHED || type == > ODP_QUEUE_TYPE_PKTIN)) { > + odp_buffer_t buf; > + > + buf = odp_schedule_buffer_alloc(handle); > + if (buf == ODP_BUFFER_INVALID) { > + ODP_ERR("queue_init: sched buf alloc failed\n"); > + return ODP_QUEUE_INVALID; > + } > + > + queue->s.sched_buf = buf; > + odp_schedule_mask_set(handle, queue->s.param.sched.prio); > + } > + > + return handle; > +} > + > + > +odp_buffer_t queue_sched_buf(odp_queue_t handle) > +{ > + queue_entry_t *queue; > + queue = queue_to_qentry(handle); > + > + return queue->s.sched_buf; > +} > + > + > +int queue_sched_atomic(odp_queue_t handle) > +{ > + queue_entry_t *queue; > + queue = queue_to_qentry(handle); > + > + return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC; > +} > + > + > +odp_queue_t odp_queue_lookup(const char *name) > +{ > + uint32_t i; > + > + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { > + queue_entry_t *queue = &queue_tbl->queue[i]; > + > + if (queue->s.status == QUEUE_STATUS_FREE) > + continue; > + > + LOCK(&queue->s.lock); > + if (strcmp(name, queue->s.name) == 0) { > + /* found it */ > + UNLOCK(&queue->s.lock); > + return queue->s.handle; > + } > + UNLOCK(&queue->s.lock); > + } > + > + return ODP_QUEUE_INVALID; > +} > + > + > +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr) > +{ > + int sched = 0; > + > + LOCK(&queue->s.lock); > + if (queue->s.head == NULL) { > + /* Empty queue */ > + queue->s.head = buf_hdr; > + queue->s.tail = buf_hdr; > + buf_hdr->pkt.next = NULL; > + } else { > + queue->s.tail->pkt.next = buf_hdr; > + queue->s.tail = buf_hdr; > + buf_hdr->pkt.next = NULL; > + } > + > + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { > + queue->s.status = QUEUE_STATUS_SCHED; > + sched = 1; /* retval: schedule queue */ > + } > + UNLOCK(&queue->s.lock); > + > + /* Add queue to scheduling */ > + if (sched == 1) > + odp_schedule_queue(queue->s.handle, > queue->s.param.sched.prio); > + > + return 0; > +} > + > + > +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], > int num) > +{ > + int sched = 0; > + int i; > + odp_buffer_hdr_t *tail; > + > + for (i = 0; i < num - 1; i++) > + buf_hdr[i]->pkt.next = buf_hdr[i+1]; > + > + tail = buf_hdr[num-1]; > + buf_hdr[num-1]->pkt.next = NULL; > + > + LOCK(&queue->s.lock); > + /* Empty queue */ > + if (queue->s.head == NULL) > + queue->s.head = buf_hdr[0]; > + else > + queue->s.tail->pkt.next = buf_hdr[0]; > + > + queue->s.tail = tail; > + > + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { > + queue->s.status = QUEUE_STATUS_SCHED; > + sched = 1; /* retval: schedule queue */ > + } > + UNLOCK(&queue->s.lock); > + > + /* Add queue to scheduling */ > + if (sched == 1) > + odp_schedule_queue(queue->s.handle, > queue->s.param.sched.prio); > + > + return 0; > +} > + > + > +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int num) > +{ > + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; > + queue_entry_t *queue; > + int i; > + > + if (num > QUEUE_MULTI_MAX) > + num = QUEUE_MULTI_MAX; > + > + queue = queue_to_qentry(handle); > + > + for (i = 0; i < num; i++) > + buf_hdr[i] = odp_buf_to_hdr(buf[i]); > + > + return queue->s.enqueue_multi(queue, buf_hdr, num); > +} > + > + > +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf) > +{ > + odp_buffer_hdr_t *buf_hdr; > + queue_entry_t *queue; > + > + queue = queue_to_qentry(handle); > + buf_hdr = odp_buf_to_hdr(buf); > + > + return queue->s.enqueue(queue, buf_hdr); > +} > + > + > +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue) > +{ > + odp_buffer_hdr_t *buf_hdr = NULL; > + > + LOCK(&queue->s.lock); > + > + if (queue->s.head == NULL) { > + /* Already empty queue */ > + if (queue->s.status == QUEUE_STATUS_SCHED && > + queue->s.type != ODP_QUEUE_TYPE_PKTIN) > + queue->s.status = QUEUE_STATUS_NOTSCHED; > + } else { > + buf_hdr = queue->s.head; > + queue->s.head = buf_hdr->pkt.next; > + buf_hdr->pkt.next = NULL; > + > + if (queue->s.head == NULL) { > + /* Queue is now empty */ > + queue->s.tail = NULL; > + } > + } > + > + UNLOCK(&queue->s.lock); > + > + return buf_hdr; > +} > + > + > +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], > int num) > +{ > + int i = 0; > + > + LOCK(&queue->s.lock); > + > + if (queue->s.head == NULL) { > + /* Already empty queue */ > + if (queue->s.status == QUEUE_STATUS_SCHED && > + queue->s.type != ODP_QUEUE_TYPE_PKTIN) > + queue->s.status = QUEUE_STATUS_NOTSCHED; > + } else { > + odp_buffer_hdr_t *hdr = queue->s.head; > + > + for (; i < num && hdr; i++) { > + buf_hdr[i] = hdr; > + /* odp_prefetch(hdr->addr); */ > + hdr = hdr->pkt.next; > + buf_hdr[i]->pkt.next = NULL; > + } > + > + queue->s.head = hdr; > + > + if (hdr == NULL) { > + /* Queue is now empty */ > + queue->s.tail = NULL; > + } > + } > + > + UNLOCK(&queue->s.lock); > + > + return i; > +} > + > + > +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int num) > +{ > + queue_entry_t *queue; > + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; > + int i, ret; > + > + if (num > QUEUE_MULTI_MAX) > + num = QUEUE_MULTI_MAX; > + > + queue = queue_to_qentry(handle); > + > + ret = queue->s.dequeue_multi(queue, buf_hdr, num); > + > + for (i = 0; i < ret; i++) > + buf[i] = (odp_buffer_t) buf_hdr[i]; > + > + return ret; > +} > + > + > +odp_buffer_t odp_queue_deq(odp_queue_t handle) > +{ > + queue_entry_t *queue; > + odp_buffer_hdr_t *buf_hdr; > + > + queue = queue_to_qentry(handle); > + buf_hdr = queue->s.dequeue(queue); > + > + if (buf_hdr) > + return (odp_buffer_t) buf_hdr; > + > + return ODP_BUFFER_INVALID; > +} > + > + > +void queue_lock(queue_entry_t *queue) > +{ > + LOCK(&queue->s.lock); > +} > + > + > +void queue_unlock(queue_entry_t *queue) > +{ > + UNLOCK(&queue->s.lock); > +} > -- > 1.9.1 > > > _______________________________________________ > lng-odp mailing list > lng-odp@lists.linaro.org > http://lists.linaro.org/mailman/listinfo/lng-odp >
On 12 July 2014 01:14, Mike Holmes <mike.holmes@linaro.org> wrote: > Adds whitespace errors when applied. > Ran checkpatch.pl before submitting the patch. Please point to the error/warning if any. > Also needs a README like the one in linux-keystone to indicate such things > as setting ./configure --with-platform=linux-dpdk > And how to then ensure dpdk is installed to resolve things like > Forgot to mention that prerequisite is, dpdk should be checked out and compiled. I will probably add it in a README and send out a patch for that. > /usr/include/stdc-predef.h:59:1: fatal error: > ../../../dpdk/build/include/rte_config.h: No such file or directory > > > On 11 July 2014 14:35, <venkatesh.vivekanandan@linaro.org> wrote: > >> From: Vincent Hsu <vincent.hsu@linaro.org> >> >> Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org> >> --- >> platform/linux-dpdk/Makefile | 158 ++++++ >> platform/linux-dpdk/Makefile.inc | 7 + >> platform/linux-dpdk/include/api/odp_buffer.h | 101 ++++ >> platform/linux-dpdk/include/api/odp_buffer_pool.h | 99 ++++ >> platform/linux-dpdk/include/api/odp_packet.h | 228 +++++++++ >> platform/linux-dpdk/include/api/odp_pktio_types.h | 45 ++ >> platform/linux-dpdk/include/odp_buffer_internal.h | 79 +++ >> .../linux-dpdk/include/odp_buffer_pool_internal.h | 90 ++++ >> platform/linux-dpdk/include/odp_packet_dpdk.h | 88 ++++ >> platform/linux-dpdk/include/odp_packet_internal.h | 140 +++++ >> .../linux-dpdk/include/odp_packet_io_internal.h | 52 ++ >> platform/linux-dpdk/source/odp_buffer.c | 102 ++++ >> platform/linux-dpdk/source/odp_buffer_pool.c | 156 ++++++ >> platform/linux-dpdk/source/odp_init.c | 113 +++++ >> platform/linux-dpdk/source/odp_packet.c | 374 ++++++++++++++ >> platform/linux-dpdk/source/odp_packet_dpdk.c | 177 +++++++ >> platform/linux-dpdk/source/odp_packet_io.c | 561 >> +++++++++++++++++++++ >> platform/linux-dpdk/source/odp_queue.c | 435 ++++++++++++++++ >> 18 files changed, 3005 insertions(+) >> create mode 100644 platform/linux-dpdk/Makefile >> create mode 100644 platform/linux-dpdk/Makefile.inc >> create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h >> create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h >> create mode 100644 platform/linux-dpdk/include/api/odp_packet.h >> create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h >> create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h >> create mode 100644 platform/linux-dpdk/include/odp_buffer_pool_internal.h >> create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h >> create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h >> create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h >> create mode 100644 platform/linux-dpdk/source/odp_buffer.c >> create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c >> create mode 100644 platform/linux-dpdk/source/odp_init.c >> create mode 100644 platform/linux-dpdk/source/odp_packet.c >> create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c >> create mode 100644 platform/linux-dpdk/source/odp_packet_io.c >> create mode 100644 platform/linux-dpdk/source/odp_queue.c >> >> diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile >> new file mode 100644 >> index 0000000..bf8d0b3 >> --- /dev/null >> +++ b/platform/linux-dpdk/Makefile >> @@ -0,0 +1,158 @@ >> +## Copyright (c) 2013, Linaro Limited >> +## All rights reserved. >> +## >> +## Redistribution and use in source and binary forms, with or without >> +## modification, are permitted provided that the following conditions >> are met: >> +## >> +## * Redistributions of source code must retain the above copyright >> notice, this >> +## list of conditions and the following disclaimer. >> +## >> +## * Redistributions in binary form must reproduce the above >> copyright notice, this >> +## list of conditions and the following disclaimer in the >> documentation and/or >> +## other materials provided with the distribution. >> +## >> +## * Neither the name of Linaro Limited nor the names of its >> contributors may be >> +## used to endorse or promote products derived from this software >> without specific >> +## prior written permission. >> +## >> +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >> "AS IS" AND >> +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >> IMPLIED >> +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >> +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE >> LIABLE >> +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >> CONSEQUENTIAL >> +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE >> GOODS OR >> +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >> HOWEVER >> +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >> LIABILITY, >> +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF >> THE USE >> +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >> + >> +.DEFAULT_GOAL := libs >> + >> +ODP_ROOT = ../.. >> +LIB_DIR = ./lib >> +DOC_DIR = ./doc >> + >> +LINUX_GENERIC_DIR = ../linux-generic >> + >> +RTE_SDK ?= $(abspath $(ODP_ROOT)/../dpdk) >> +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build) >> +RTE_LIB ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a) >> + >> +PLAT_CFLAGS = -include $(RTE_OUTPUT)/include/rte_config.h >> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include >> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch >> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env >> +PLAT_CFLAGS += -msse4.2 >> + >> +EXTRA_CFLAGS += $(PLAT_CFLAGS) >> +EXTRA_CFLAGS += -I./include >> +EXTRA_CFLAGS += -I./include/api >> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include >> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api >> +EXTRA_CFLAGS += -I$(ODP_ROOT)/include >> + >> +include $(ODP_ROOT)/Makefile.inc >> +STATIC_LIB = ./lib/libodp.a >> + >> +# >> +# Object files >> +# >> +OBJS = >> +OBJS += $(OBJ_DIR)/odp_barrier.o >> +OBJS += $(OBJ_DIR)/odp_buffer.o >> +OBJS += $(OBJ_DIR)/odp_buffer_pool.o >> +OBJS += $(OBJ_DIR)/odp_coremask.o >> +OBJS += $(OBJ_DIR)/odp_init.o >> +OBJS += $(OBJ_DIR)/odp_linux.o >> +OBJS += $(OBJ_DIR)/odp_packet.o >> +OBJS += $(OBJ_DIR)/odp_packet_flags.o >> +OBJS += $(OBJ_DIR)/odp_packet_io.o >> +OBJS += $(OBJ_DIR)/odp_packet_socket.o >> +OBJS += $(OBJ_DIR)/odp_queue.o >> +OBJS += $(OBJ_DIR)/odp_schedule.o >> +OBJS += $(OBJ_DIR)/odp_shared_memory.o >> +OBJS += $(OBJ_DIR)/odp_spinlock.o >> +OBJS += $(OBJ_DIR)/odp_system_info.o >> +OBJS += $(OBJ_DIR)/odp_thread.o >> +OBJS += $(OBJ_DIR)/odp_ticketlock.o >> +OBJS += $(OBJ_DIR)/odp_time.o >> +OBJS += $(OBJ_DIR)/odp_timer.o >> +OBJS += $(OBJ_DIR)/odp_ring.o >> +OBJS += $(OBJ_DIR)/odp_rwlock.o >> +OBJS += $(OBJ_DIR)/odp_packet_dpdk.o >> + >> +DEPS = $(OBJS:.o=.d) >> + >> +.PHONY: all >> +all: libs docs >> + >> +-include $(DEPS) >> + >> +#$(OBJ_DIR): >> +# $(MKDIR) $(OBJ_DIR) >> + >> +$(LIB_DIR): >> + $(MKDIR) $(LIB_DIR) >> + >> +$(DOC_DIR): >> + $(MKDIR) $(DOC_DIR)/html >> + $(MKDIR) $(DOC_DIR)/latex >> + >> +# >> +# Compile rules >> +# >> +vpath %.c source:$(LINUX_GENERIC_DIR)/source >> + >> +$(OBJ_DIR)/%.o: %.c >> + $(ECHO) " CC $<" >> + $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $< >> + >> +# >> +# Lib rule >> +# >> +$(OBJ_DIR)/libodp.o: $(OBJS) >> + $(ECHO) " LD $@" >> + $(LD) -r -o $@ $(OBJS) $(RTE_LIB) >> + >> +$(STATIC_LIB): $(OBJ_DIR)/libodp.o >> + $(ECHO) " AR $@" >> + $(AR) -cr $@ $(OBJ_DIR)/libodp.o >> + >> + >> +clean: >> + $(RMDIR) $(OBJ_DIR) >> + $(RMDIR) $(LIB_DIR) >> + $(RMDIR) $(DOC_DIR) >> + $(RM) Doxyfile >> + >> +Doxyfile: Doxyfile.in >> + doxygen -u - < $< > $@ >> + >> +.PHONY: docs >> +docs: $(DOC_DIR) Doxyfile ./include/odp*.h >> + doxygen >> + >> +.PHONY: docs_install >> +docs_install: docs >> + $(COPY) doc $(DESTDIR) >> + >> +.PHONY: pdf >> +pdf: docs >> + make --directory doc/latex refman.pdf 1> /dev/null >> + >> +.PHONY: libs >> +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB) >> + >> +.PHONY: lib_install >> +lib_install: libs >> + install -d $(DESTDIR)/lib >> + install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/ >> + >> +.PHONY: headers_install >> +headers_install: libs >> + $(ECHO) Installing headers to $(DESTDIR)/include >> + $(COPY) $(ODP_ROOT)/include $(DESTDIR) >> + $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/ >> + $(COPY) include/api/* $(DESTDIR)/include/ >> + >> +install: lib_install headers_install >> diff --git a/platform/linux-dpdk/Makefile.inc >> b/platform/linux-dpdk/Makefile.inc >> new file mode 100644 >> index 0000000..fe7679b >> --- /dev/null >> +++ b/platform/linux-dpdk/Makefile.inc >> @@ -0,0 +1,7 @@ >> +# Copyright (c) 2013, Linaro Limited >> +# All rights reserved. >> +# >> +# SPDX-License-Identifier: BSD-3-Clause >> + >> +STD_LIBS += -ldl >> + >> diff --git a/platform/linux-dpdk/include/api/odp_buffer.h >> b/platform/linux-dpdk/include/api/odp_buffer.h >> new file mode 100644 >> index 0000000..286d9e6 >> --- /dev/null >> +++ b/platform/linux-dpdk/include/api/odp_buffer.h >> @@ -0,0 +1,101 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> + >> +/** >> + * @file >> + * >> + * ODP buffer descriptor >> + */ >> + >> +#ifndef ODP_BUFFER_H_ >> +#define ODP_BUFFER_H_ >> + >> +#ifdef __cplusplus >> +extern "C" { >> +#endif >> + >> + >> + >> +#include <odp_std_types.h> >> + >> + >> + >> + >> + >> +/** >> + * ODP buffer >> + */ >> +typedef unsigned long odp_buffer_t; >> + >> + >> +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */ >> + >> + >> +/** >> + * Buffer start address >> + * >> + * @param buf Buffer handle >> + * >> + * @return Buffer start address >> + */ >> +void *odp_buffer_addr(odp_buffer_t buf); >> + >> +/** >> + * Buffer maximum data size >> + * >> + * @param buf Buffer handle >> + * >> + * @return Buffer maximum data size >> + */ >> +size_t odp_buffer_size(odp_buffer_t buf); >> + >> +/** >> + * Buffer type >> + * >> + * @param buf Buffer handle >> + * >> + * @return Buffer type >> + */ >> +int odp_buffer_type(odp_buffer_t buf); >> + >> +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */ >> +#define ODP_BUFFER_TYPE_RAW 0 /**< Raw buffer */ >> +#define ODP_BUFFER_TYPE_PACKET 1 /**< Packet buffer */ >> +#define ODP_BUFFER_TYPE_TIMER 2 /**< Timer buffer */ >> + >> +/** >> + * Tests if buffer is part of a scatter/gather list >> + * >> + * @param buf Buffer handle >> + * >> + * @return 1 if belongs to a scatter list, otherwise 0 >> + */ >> +int odp_buffer_is_scatter(odp_buffer_t buf); >> + >> +/** >> + * Tests if buffer is valid >> + * >> + * @param buf Buffer handle >> + * >> + * @return 1 if valid, otherwise 0 >> + */ >> +int odp_buffer_is_valid(odp_buffer_t buf); >> + >> +/** >> + * Print buffer metadata to STDOUT >> + * >> + * @param buf Buffer handle >> + * >> + */ >> +void odp_buffer_print(odp_buffer_t buf); >> + >> + >> +#ifdef __cplusplus >> +} >> +#endif >> + >> +#endif >> diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h >> b/platform/linux-dpdk/include/api/odp_buffer_pool.h >> new file mode 100644 >> index 0000000..4b75cf5 >> --- /dev/null >> +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h >> @@ -0,0 +1,99 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> + >> +/** >> + * @file >> + * >> + * ODP buffer pool >> + */ >> + >> +#ifndef ODP_BUFFER_POOL_H_ >> +#define ODP_BUFFER_POOL_H_ >> + >> +#ifdef __cplusplus >> +extern "C" { >> +#endif >> + >> + >> + >> +#include <odp_std_types.h> >> +#include <odp_buffer.h> >> + >> +/** Maximum queue name lenght in chars */ >> +#define ODP_BUFFER_POOL_NAME_LEN 32 >> + >> +/** Invalid buffer pool */ >> +#define ODP_BUFFER_POOL_INVALID (0xffffffff) >> + >> +/** ODP buffer pool */ >> +typedef unsigned long odp_buffer_pool_t; >> + >> + >> +/** >> + * Create a buffer pool >> + * >> + * @param name Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1 >> chars) >> + * @param base_addr Pool base address >> + * @param size Pool size in bytes >> + * @param buf_size Buffer size in bytes >> + * @param buf_align Minimum buffer alignment >> + * @param buf_type Buffer type >> + * >> + * @return Buffer pool handle >> + */ >> +odp_buffer_pool_t odp_buffer_pool_create(const char *name, >> + void *base_addr, uint64_t size, >> + size_t buf_size, size_t >> buf_align, >> + int buf_type); >> + >> + >> +/** >> + * Find a buffer pool by name >> + * >> + * @param name Name of the pool >> + * >> + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found. >> + */ >> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name); >> + >> + >> +/** >> + * Print buffer pool info >> + * >> + * @param pool Pool handle >> + * >> + */ >> +void odp_buffer_pool_print(odp_buffer_pool_t pool); >> + >> + >> + >> +/** >> + * Buffer alloc >> + * >> + * @param pool Pool handle >> + * >> + * @return Buffer handle or ODP_BUFFER_INVALID >> + */ >> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool); >> + >> + >> +/** >> + * Buffer free >> + * >> + * @param buf Buffer handle >> + * >> + */ >> +void odp_buffer_free(odp_buffer_t buf); >> + >> + >> + >> + >> +#ifdef __cplusplus >> +} >> +#endif >> + >> +#endif >> diff --git a/platform/linux-dpdk/include/api/odp_packet.h >> b/platform/linux-dpdk/include/api/odp_packet.h >> new file mode 100644 >> index 0000000..bdb3417 >> --- /dev/null >> +++ b/platform/linux-dpdk/include/api/odp_packet.h >> @@ -0,0 +1,228 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> + >> +/** >> + * @file >> + * >> + * ODP packet descriptor >> + */ >> + >> +#ifndef ODP_PACKET_H_ >> +#define ODP_PACKET_H_ >> + >> +#ifdef __cplusplus >> +extern "C" { >> +#endif >> + >> +#include <odp_buffer.h> >> + >> + >> +/** >> + * ODP packet descriptor >> + */ >> +typedef unsigned long odp_packet_t; >> + >> + >> +/** Invalid packet */ >> +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID >> + >> +/** Invalid offset */ >> +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1) >> + >> + >> +/** >> + * Initialize the packet >> + * >> + * Needs to be called if the user allocates a packet buffer, i.e. the >> packet >> + * has not been received from I/O through ODP. >> + * >> + * @param pkt Packet handle >> + */ >> +void odp_packet_init(odp_packet_t pkt); >> + >> +/** >> + * Convert from packet handle to buffer handle >> + * >> + * @param buf Buffer handle >> + * >> + * @return Packet handle >> + */ >> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf); >> + >> +/** >> + * Convert from buffer handle to packet handle >> + * >> + * @param pkt Packet handle >> + * >> + * @return Buffer handle >> + */ >> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt); >> + >> +/** >> + * Set the packet length >> + * >> + * @param pkt Packet handle >> + * @param len Length of packet in bytes >> + */ >> +void odp_packet_set_len(odp_packet_t pkt, size_t len); >> + >> +/** >> + * Get the packet length >> + * >> + * @param pkt Packet handle >> + * >> + * @return Packet length in bytes >> + */ >> +size_t odp_packet_get_len(odp_packet_t pkt); >> + >> +/** >> + * Get address to the start of the packet buffer >> + * >> + * The address of the packet buffer is not necessarily the same as the >> start >> + * address of the received frame, e.g. an eth frame may be offset by 2 >> or 6 >> + * bytes to ensure 32 or 64-bit alignment of the IP header. >> + * Use odp_packet_l2(pkt) to get the start address of a received valid >> frame >> + * or odp_packet_start(pkt) to get the start address even if no valid L2 >> header >> + * could be found. >> + * >> + * @param pkt Packet handle >> + * >> + * @return Pointer to the start of the packet buffer >> + * >> + * @see odp_packet_l2(), odp_packet_start() >> + */ >> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt); >> + >> +/** >> + * Get pointer to the start of the received frame >> + * >> + * The address of the packet buffer is not necessarily the same as the >> start >> + * address of the received frame, e.g. an eth frame may be offset by 2 >> or 6 >> + * bytes to ensure 32 or 64-bit alignment of the IP header. >> + * Use odp_packet_l2(pkt) to get the start address of a received valid >> eth frame >> + * >> + * odp_packet_start() will always return a pointer to the start of the >> frame, >> + * even if the frame is unrecognized and no valid L2 header could be >> found. >> + * >> + * @param pkt Packet handle >> + * >> + * @return Pointer to the start of the received frame >> + * >> + * @see odp_packet_l2(), odp_packet_buf_addr() >> + */ >> +uint8_t *odp_packet_start(odp_packet_t pkt); >> + >> +/** >> + * Get pointer to the start of the L2 frame >> + * >> + * The L2 frame header address is not necessarily the same as the >> address of the >> + * packet buffer, see odp_packet_buf_addr() >> + * >> + * @param pkt Packet handle >> + * >> + * @return Pointer to L2 header or NULL if not found >> + * >> + * @see odp_packet_buf_addr(), odp_packet_start() >> + */ >> +uint8_t *odp_packet_l2(odp_packet_t pkt); >> + >> +/** >> + * Return the byte offset from the packet buffer to the L2 frame >> + * >> + * @param pkt Packet handle >> + * >> + * @return L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found >> + */ >> +size_t odp_packet_l2_offset(odp_packet_t pkt); >> + >> +/** >> + * Set the byte offset to the L2 frame >> + * >> + * @param pkt Packet handle >> + * @param offset L2 byte offset >> + */ >> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset); >> + >> + >> +/** >> + * Get pointer to the start of the L3 packet >> + * >> + * @param pkt Packet handle >> + * >> + * @return Pointer to L3 packet or NULL if not found >> + * >> + */ >> +uint8_t *odp_packet_l3(odp_packet_t pkt); >> + >> +/** >> + * Return the byte offset from the packet buffer to the L3 packet >> + * >> + * @param pkt Packet handle >> + * >> + * @return L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found >> + */ >> +size_t odp_packet_l3_offset(odp_packet_t pkt); >> + >> +/** >> + * Set the byte offset to the L3 packet >> + * >> + * @param pkt Packet handle >> + * @param offset L3 byte offset >> + */ >> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset); >> + >> + >> +/** >> + * Get pointer to the start of the L4 packet >> + * >> + * @param pkt Packet handle >> + * >> + * @return Pointer to L4 packet or NULL if not found >> + * >> + */ >> +uint8_t *odp_packet_l4(odp_packet_t pkt); >> + >> +/** >> + * Return the byte offset from the packet buffer to the L4 packet >> + * >> + * @param pkt Packet handle >> + * >> + * @return L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found >> + */ >> +size_t odp_packet_l4_offset(odp_packet_t pkt); >> + >> +/** >> + * Set the byte offset to the L4 packet >> + * >> + * @param pkt Packet handle >> + * @param offset L4 byte offset >> + */ >> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset); >> + >> +/** >> + * Print (debug) information about the packet >> + * >> + * @param pkt Packet handle >> + */ >> +void odp_packet_print(odp_packet_t pkt); >> + >> +/** >> + * Copy contents and metadata from pkt_src to pkt_dst >> + * Useful when creating copies of packets >> + * >> + * @param pkt_dst Destination packet >> + * @param pkt_src Source packet >> + * >> + * @return 0 if successful >> + */ >> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src); >> + >> +#ifdef __cplusplus >> +} >> +#endif >> + >> +#endif >> diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h >> b/platform/linux-dpdk/include/api/odp_pktio_types.h >> new file mode 100644 >> index 0000000..b23e6da >> --- /dev/null >> +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h >> @@ -0,0 +1,45 @@ >> + >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#ifndef ODP_PKTIO_TYPES_H >> +#define ODP_PKTIO_TYPES_H >> + >> +#ifdef __cplusplus >> +extern "C" { >> +#endif >> + >> +/* We should ensure that future enum values will never overlap, otherwise >> + * applications that want netmap suport might get in trouble if the odp >> lib >> + * was not built with netmap support and there are more types define >> below >> + */ >> + >> +typedef enum { >> + ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1, >> + ODP_PKTIO_TYPE_SOCKET_MMSG, >> + ODP_PKTIO_TYPE_SOCKET_MMAP, >> + ODP_PKTIO_TYPE_NETMAP, >> + ODP_PKTIO_TYPE_DPDK, >> +} odp_pktio_type_t; >> + >> +#include <odp_pktio_socket.h> >> +#ifdef ODP_HAVE_NETMAP >> +#include <odp_pktio_netmap.h> >> +#endif >> + >> +typedef union odp_pktio_params_t { >> + odp_pktio_type_t type; >> + socket_params_t sock_params; >> +#ifdef ODP_HAVE_NETMAP >> + netmap_params_t nm_params; >> +#endif >> +} odp_pktio_params_t; >> + >> +#ifdef __cplusplus >> +} >> +#endif >> + >> +#endif >> diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h >> b/platform/linux-dpdk/include/odp_buffer_internal.h >> new file mode 100644 >> index 0000000..a47107c >> --- /dev/null >> +++ b/platform/linux-dpdk/include/odp_buffer_internal.h >> @@ -0,0 +1,79 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> + >> +/** >> + * @file >> + * >> + * ODP buffer descriptor - implementation internal >> + */ >> + >> +#ifndef ODP_BUFFER_INTERNAL_H_ >> +#define ODP_BUFFER_INTERNAL_H_ >> + >> +#ifdef __cplusplus >> +extern "C" { >> +#endif >> + >> +#include <odp_std_types.h> >> +#include <odp_atomic.h> >> +#include <odp_buffer_pool.h> >> +#include <odp_buffer.h> >> +#include <odp_debug.h> >> +#include <odp_align.h> >> +#include <rte_mbuf.h> >> + >> +/* TODO: move these to correct files */ >> + >> +typedef uint64_t odp_phys_addr_t; >> + >> +#define ODP_BUFFER_MAX_INDEX (ODP_BUFFER_MAX_BUFFERS - 2) >> +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1) >> + >> +#define ODP_BUFS_PER_CHUNK 16 >> +#define ODP_BUFS_PER_SCATTER 4 >> + >> +#define ODP_BUFFER_TYPE_CHUNK 0xffff >> + >> + >> +#define ODP_BUFFER_POOL_BITS 4 >> +#define ODP_BUFFER_INDEX_BITS (32 - ODP_BUFFER_POOL_BITS) >> +#define ODP_BUFFER_MAX_POOLS (1 << ODP_BUFFER_POOL_BITS) >> +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS) >> + >> +typedef union odp_buffer_bits_t { >> + uint32_t u32; >> + odp_buffer_t handle; >> + >> + struct { >> + uint32_t pool:ODP_BUFFER_POOL_BITS; >> + uint32_t index:ODP_BUFFER_INDEX_BITS; >> + }; >> +} odp_buffer_bits_t; >> + >> + >> +/* forward declaration */ >> +struct odp_buffer_hdr_t; >> + >> + >> +typedef struct rte_mbuf odp_buffer_hdr_t; >> + >> + >> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf); >> + >> + >> +#ifdef __cplusplus >> +} >> +#endif >> + >> +#endif >> + >> + >> + >> + >> + >> + >> + >> diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h >> b/platform/linux-dpdk/include/odp_buffer_pool_internal.h >> new file mode 100644 >> index 0000000..1a36655 >> --- /dev/null >> +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h >> @@ -0,0 +1,90 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> + >> +/** >> + * @file >> + * >> + * ODP buffer pool - internal header >> + */ >> + >> +#ifndef ODP_BUFFER_POOL_INTERNAL_H_ >> +#define ODP_BUFFER_POOL_INTERNAL_H_ >> + >> +#ifdef __cplusplus >> +extern "C" { >> +#endif >> + >> +#include <odp_std_types.h> >> +#include <odp_buffer_pool.h> >> +#include <odp_buffer_internal.h> >> +#include <odp_align.h> >> +#include <odp_hints.h> >> +#include <odp_config.h> >> +#include <odp_debug.h> >> + >> +/* for DPDK */ >> +#include <rte_mempool.h> >> + >> +/* Use ticketlock instead of spinlock */ >> +#define POOL_USE_TICKETLOCK >> + >> +/* Extra error checks */ >> +/* #define POOL_ERROR_CHECK */ >> + >> + >> +#ifdef POOL_USE_TICKETLOCK >> +#include <odp_ticketlock.h> >> +#else >> +#include <odp_spinlock.h> >> +#endif >> + >> + >> +struct pool_entry_s { >> +#ifdef POOL_USE_TICKETLOCK >> + odp_ticketlock_t lock ODP_ALIGNED_CACHE; >> +#else >> + odp_spinlock_t lock ODP_ALIGNED_CACHE; >> +#endif >> + >> + uint64_t free_bufs; >> + char name[ODP_BUFFER_POOL_NAME_LEN]; >> + >> + >> + odp_buffer_pool_t pool ODP_ALIGNED_CACHE; >> + uintptr_t buf_base; >> + size_t buf_size; >> + size_t buf_offset; >> + uint64_t num_bufs; >> + void *pool_base_addr; >> + uint64_t pool_size; >> + size_t payload_size; >> + size_t payload_align; >> + int buf_type; >> + size_t hdr_size; >> +}; >> + >> + >> +extern void *pool_entry_ptr[]; >> + >> + >> +static inline void *get_pool_entry(odp_buffer_pool_t pool_id) >> +{ >> + return pool_entry_ptr[pool_id]; >> +} >> + >> + >> +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf) >> +{ >> + return (odp_buffer_hdr_t *)buf; >> +} >> + >> + >> +#ifdef __cplusplus >> +} >> +#endif >> + >> +#endif >> diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h >> b/platform/linux-dpdk/include/odp_packet_dpdk.h >> new file mode 100644 >> index 0000000..0b3db08 >> --- /dev/null >> +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h >> @@ -0,0 +1,88 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#ifndef ODP_PACKET_DPDK_H >> +#define ODP_PACKET_DPDK_H >> + >> +#include <stdint.h> >> +#include <net/if.h> >> + >> +#include <helper/odp_eth.h> >> +#include <helper/odp_packet_helper.h> >> +#include <odp_align.h> >> +#include <odp_debug.h> >> +#include <odp_packet.h> >> +#include <odp_packet_internal.h> >> +#include <odp_buffer_pool.h> >> +#include <odp_buffer_pool_internal.h> >> +#include <odp_buffer_internal.h> >> +#include <odp_std_types.h> >> + >> +#include <rte_config.h> >> +#include <rte_memory.h> >> +#include <rte_memzone.h> >> +#include <rte_launch.h> >> +#include <rte_tailq.h> >> +#include <rte_eal.h> >> +#include <rte_per_lcore.h> >> +#include <rte_lcore.h> >> +#include <rte_branch_prediction.h> >> +#include <rte_prefetch.h> >> +#include <rte_cycles.h> >> +#include <rte_errno.h> >> +#include <rte_debug.h> >> +#include <rte_log.h> >> +#include <rte_byteorder.h> >> +#include <rte_pci.h> >> +#include <rte_random.h> >> +#include <rte_ether.h> >> +#include <rte_ethdev.h> >> +#include <rte_hash.h> >> +#include <rte_jhash.h> >> +#include <rte_hash_crc.h> >> + >> + >> +#define ODP_DPDK_MODE_HW 0 >> +#define ODP_DPDK_MODE_SW 1 >> + >> +#define DPDK_BLOCKING_IO >> + >> +/** Packet socket using dpdk mmaped rings for both Rx and Tx */ >> +typedef struct { >> + odp_buffer_pool_t pool; >> + >> + /********************************/ >> + char ifname[32]; >> + uint8_t portid; >> + uint16_t queueid; >> +} pkt_dpdk_t; >> + >> +/** >> + * Configure an interface to work in dpdk mode >> + */ >> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, >> + odp_buffer_pool_t pool); >> + >> +/** >> + * Switch interface from dpdk mode to normal mode >> + */ >> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk); >> + >> +/** >> + * Receive packets using dpdk >> + */ >> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], >> + unsigned len); >> + >> +/** >> + * Send packets using dpdk >> + */ >> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], >> + unsigned len); >> + >> +int odp_init_dpdk(void); >> +#endif >> + >> diff --git a/platform/linux-dpdk/include/odp_packet_internal.h >> b/platform/linux-dpdk/include/odp_packet_internal.h >> new file mode 100644 >> index 0000000..d9057a2 >> --- /dev/null >> +++ b/platform/linux-dpdk/include/odp_packet_internal.h >> @@ -0,0 +1,140 @@ >> +/* Copyright (c) 2014, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> + >> +/** >> + * @file >> + * >> + * ODP packet descriptor - implementation internal >> + */ >> + >> +#ifndef ODP_PACKET_INTERNAL_H_ >> +#define ODP_PACKET_INTERNAL_H_ >> + >> +#ifdef __cplusplus >> +extern "C" { >> +#endif >> + >> +#include <odp_align.h> >> +#include <odp_debug.h> >> +#include <odp_buffer_internal.h> >> +#include <odp_buffer_pool_internal.h> >> +#include <odp_packet.h> >> +#include <odp_packet_io.h> >> + >> +/** >> + * Packet input & protocol flags >> + */ >> +typedef union { >> + /* All input flags */ >> + uint32_t all; >> + >> + struct { >> + /* Bitfield flags for each protocol */ >> + uint32_t l2:1; /**< known L2 protocol present */ >> + uint32_t l3:1; /**< known L3 protocol present */ >> + uint32_t l4:1; /**< known L4 protocol present */ >> + >> + uint32_t eth:1; /**< Ethernet */ >> + uint32_t jumbo:1; /**< Jumbo frame */ >> + uint32_t vlan:1; /**< VLAN hdr found */ >> + uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */ >> + >> + uint32_t arp:1; /**< ARP */ >> + >> + uint32_t ipv4:1; /**< IPv4 */ >> + uint32_t ipv6:1; /**< IPv6 */ >> + uint32_t ipfrag:1; /**< IP fragment */ >> + uint32_t ipopt:1; /**< IP optional headers */ >> + uint32_t ipsec:1; /**< IPSec decryption may be needed >> */ >> + >> + uint32_t udp:1; /**< UDP */ >> + uint32_t tcp:1; /**< TCP */ >> + uint32_t sctp:1; /**< SCTP */ >> + uint32_t icmp:1; /**< ICMP */ >> + }; >> +} input_flags_t; >> + >> +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t), >> INPUT_FLAGS_SIZE_ERROR); >> + >> +/** >> + * Packet error flags >> + */ >> +typedef union { >> + /* All error flags */ >> + uint32_t all; >> + >> + struct { >> + /* Bitfield flags for each detected error */ >> + uint32_t frame_len:1; /**< Frame length error */ >> + uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD >> */ >> + uint32_t ip_err:1; /**< IP error, checks TBD */ >> + uint32_t tcp_err:1; /**< TCP error, checks TBD */ >> + uint32_t udp_err:1; /**< UDP error, checks TBD */ >> + }; >> +} error_flags_t; >> + >> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t), >> ERROR_FLAGS_SIZE_ERROR); >> + >> +/** >> + * Packet output flags >> + */ >> +typedef union { >> + /* All output flags */ >> + uint32_t all; >> + >> + struct { >> + /* Bitfield flags for each output option */ >> + uint32_t l4_chksum:1; /**< Request L4 checksum >> calculation */ >> + }; >> +} output_flags_t; >> + >> +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), >> OUTPUT_FLAGS_SIZE_ERROR); >> + >> +/** >> + * Internal Packet header >> + */ >> +typedef struct { >> + /* common buffer header */ >> + odp_buffer_hdr_t buf_hdr; >> + >> + input_flags_t input_flags; >> + error_flags_t error_flags; >> + output_flags_t output_flags; >> + >> + uint32_t frame_offset; /**< offset to start of frame, even on >> error */ >> + uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */ >> + uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */ >> + uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also >> ICMP) */ >> + >> + uint32_t frame_len; >> + >> + odp_pktio_t input; >> + >> + uint32_t pad; >> + uint8_t payload[]; >> + >> +} odp_packet_hdr_t; >> + >> +/** >> + * Return the packet header >> + */ >> +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt) >> +{ >> + return (odp_packet_hdr_t *)pkt; >> +} >> + >> +/** >> + * Parse packet and set internal metadata >> + */ >> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset); >> + >> +#ifdef __cplusplus >> +} >> +#endif >> + >> +#endif >> + >> diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h >> b/platform/linux-dpdk/include/odp_packet_io_internal.h >> new file mode 100644 >> index 0000000..5948063 >> --- /dev/null >> +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h >> @@ -0,0 +1,52 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> + >> +/** >> + * @file >> + * >> + * ODP packet IO - implementation internal >> + */ >> + >> +#ifndef ODP_PACKET_IO_INTERNAL_H_ >> +#define ODP_PACKET_IO_INTERNAL_H_ >> + >> +#ifdef __cplusplus >> +extern "C" { >> +#endif >> + >> +#include <odp_spinlock.h> >> +#include <odp_packet_socket.h> >> +#ifdef ODP_HAVE_NETMAP >> +#include <odp_packet_netmap.h> >> +#endif >> +#include <odp_packet_dpdk.h> >> + >> +struct pktio_entry { >> + odp_spinlock_t lock; /**< entry spinlock */ >> + int taken; /**< is entry taken(1) or free(0) >> */ >> + odp_queue_t inq_default; /**< default input queue, if set >> */ >> + odp_queue_t outq_default; /**< default out queue */ >> + odp_pktio_params_t params; /**< pktio parameters */ >> + pkt_sock_t pkt_sock; /**< using socket API for IO */ >> + pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap API for IO >> */ >> +#ifdef ODP_HAVE_NETMAP >> + pkt_netmap_t pkt_nm; /**< using netmap API for IO */ >> +#endif >> + pkt_dpdk_t pkt_dpdk; /**< using DPDK API for IO */ >> +}; >> + >> +typedef union { >> + struct pktio_entry s; >> + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct >> pktio_entry))]; >> +} pktio_entry_t; >> + >> +#ifdef __cplusplus >> +} >> +#endif >> + >> +#endif >> + >> diff --git a/platform/linux-dpdk/source/odp_buffer.c >> b/platform/linux-dpdk/source/odp_buffer.c >> new file mode 100644 >> index 0000000..bfb5ff6 >> --- /dev/null >> +++ b/platform/linux-dpdk/source/odp_buffer.c >> @@ -0,0 +1,102 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include <odp_buffer.h> >> +#include <odp_buffer_internal.h> >> +#include <odp_buffer_pool_internal.h> >> + >> +#include <string.h> >> +#include <stdio.h> >> + >> + >> +void *odp_buffer_addr(odp_buffer_t buf) >> +{ >> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >> + >> + return hdr->buf_addr; >> +} >> + >> + >> +size_t odp_buffer_size(odp_buffer_t buf) >> +{ >> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >> + >> + return hdr->buf_len; >> +} >> + >> + >> +int odp_buffer_type(odp_buffer_t buf) >> +{ >> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >> + >> + return hdr->type; >> +} >> + >> + >> +int odp_buffer_is_scatter(odp_buffer_t buf) >> +{ >> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >> + >> + if (hdr->refcnt == 0) >> + return 0; >> + else >> + return 1; >> +} >> + >> + >> +int odp_buffer_is_valid(odp_buffer_t buf) >> +{ >> + odp_buffer_bits_t handle; >> + >> + handle.u32 = buf; >> + >> + return (handle.index != ODP_BUFFER_INVALID_INDEX); >> +} >> + >> + >> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf) >> +{ >> + odp_buffer_hdr_t *hdr; >> + int len = 0; >> + >> + if (!odp_buffer_is_valid(buf)) { >> + printf("Buffer is not valid.\n"); >> + return len; >> + } >> + >> + hdr = odp_buf_to_hdr(buf); >> + >> + len += snprintf(&str[len], n-len, >> + "Buffer\n"); >> + len += snprintf(&str[len], n-len, >> + " pool %"PRIu64"\n", (int64_t) >> hdr->pool); >> + len += snprintf(&str[len], n-len, >> + " phy_addr %"PRIu64"\n", hdr->buf_physaddr); >> + len += snprintf(&str[len], n-len, >> + " addr %p\n", hdr->buf_addr); >> + len += snprintf(&str[len], n-len, >> + " size %u\n", hdr->buf_len); >> + len += snprintf(&str[len], n-len, >> + " ref_count %i\n", hdr->refcnt); >> + len += snprintf(&str[len], n-len, >> + " type %i\n", hdr->type); >> + >> + return len; >> +} >> + >> + >> +void odp_buffer_print(odp_buffer_t buf) >> +{ >> + int max_len = 512; >> + char str[max_len]; >> + int len; >> + >> + len = odp_buffer_snprint(str, max_len-1, buf); >> + str[len] = 0; >> + >> + printf("\n%s\n", str); >> +} >> + >> diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c >> b/platform/linux-dpdk/source/odp_buffer_pool.c >> new file mode 100644 >> index 0000000..de90275 >> --- /dev/null >> +++ b/platform/linux-dpdk/source/odp_buffer_pool.c >> @@ -0,0 +1,156 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include <odp_std_types.h> >> +#include <odp_buffer_pool.h> >> +#include <odp_buffer_pool_internal.h> >> +#include <odp_buffer_internal.h> >> +#include <odp_packet_internal.h> >> +#include <odp_shared_memory.h> >> +#include <odp_align.h> >> +#include <odp_internal.h> >> +#include <odp_config.h> >> +#include <odp_hints.h> >> +#include <odp_debug.h> >> + >> +#include <string.h> >> +#include <stdlib.h> >> + >> +/* for DPDK */ >> +#include <odp_packet_dpdk.h> >> + >> +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) >> +#define NB_MBUF 8192 >> + >> +#ifdef POOL_USE_TICKETLOCK >> +#include <odp_ticketlock.h> >> +#define LOCK(a) odp_ticketlock_lock(a) >> +#define UNLOCK(a) odp_ticketlock_unlock(a) >> +#define LOCK_INIT(a) odp_ticketlock_init(a) >> +#else >> +#include <odp_spinlock.h> >> +#define LOCK(a) odp_spinlock_lock(a) >> +#define UNLOCK(a) odp_spinlock_unlock(a) >> +#define LOCK_INIT(a) odp_spinlock_init(a) >> +#endif >> + >> + >> +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS >> +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS >> +#endif >> + >> +#define NULL_INDEX ((uint32_t)-1) >> + >> + >> +typedef union pool_entry_u { >> + struct pool_entry_s s; >> + >> + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct >> pool_entry_s))]; >> + >> +} pool_entry_t; >> + >> + >> +typedef struct pool_table_t { >> + pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS]; >> + >> +} pool_table_t; >> + >> + >> +/* The pool table */ >> +static pool_table_t *pool_tbl; >> + >> +/* Pool entry pointers (for inlining) */ >> +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS]; >> + >> + >> +int odp_buffer_pool_init_global(void) >> +{ >> + odp_buffer_pool_t i; >> + >> + pool_tbl = odp_shm_reserve("odp_buffer_pools", >> + sizeof(pool_table_t), >> + sizeof(pool_entry_t)); >> + >> + if (pool_tbl == NULL) >> + return -1; >> + >> + memset(pool_tbl, 0, sizeof(pool_table_t)); >> + >> + >> + for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) { >> + /* init locks */ >> + pool_entry_t *pool = &pool_tbl->pool[i]; >> + LOCK_INIT(&pool->s.lock); >> + pool->s.pool = i; >> + >> + pool_entry_ptr[i] = pool; >> + } >> + >> + ODP_DBG("\nBuffer pool init global\n"); >> + ODP_DBG(" pool_entry_s size %zu\n", sizeof(struct >> pool_entry_s)); >> + ODP_DBG(" pool_entry_t size %zu\n", sizeof(pool_entry_t)); >> + ODP_DBG(" odp_buffer_hdr_t size %zu\n", >> sizeof(odp_buffer_hdr_t)); >> + ODP_DBG("\n"); >> + >> + return 0; >> +} >> + >> + >> +odp_buffer_pool_t odp_buffer_pool_create(const char *name, >> + void *base_addr, uint64_t size, >> + size_t buf_size, size_t >> buf_align, >> + int buf_type) >> +{ >> + struct rte_mempool *pktmbuf_pool = NULL; >> + ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n", name, >> + (uint64_t) base_addr, (unsigned) size, >> + (unsigned) buf_size, (unsigned) buf_align, >> + buf_type); >> + >> + pktmbuf_pool = >> + rte_mempool_create(name, NB_MBUF, >> + MBUF_SIZE, 32, >> + sizeof(struct >> rte_pktmbuf_pool_private), >> + rte_pktmbuf_pool_init, NULL, >> + rte_pktmbuf_init, NULL, >> + rte_socket_id(), 0); >> + if (pktmbuf_pool == NULL) { >> + ODP_ERR("Cannot init DPDK mbuf pool\n"); >> + return -1; >> + } >> + >> + return (odp_buffer_pool_t) pktmbuf_pool; >> +} >> + >> + >> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name) >> +{ >> + struct rte_mempool *mp = NULL; >> + >> + mp = rte_mempool_lookup(name); >> + if (mp == NULL) >> + return ODP_BUFFER_POOL_INVALID; >> + >> + return (odp_buffer_pool_t)mp; >> +} >> + >> + >> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id) >> +{ >> + return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool >> *)pool_id); >> +} >> + >> + >> +void odp_buffer_free(odp_buffer_t buf) >> +{ >> + rte_pktmbuf_free((struct rte_mbuf *)buf); >> +} >> + >> + >> +void odp_buffer_pool_print(odp_buffer_pool_t pool_id) >> +{ >> + rte_mempool_dump((const struct rte_mempool *)pool_id); >> +} >> diff --git a/platform/linux-dpdk/source/odp_init.c >> b/platform/linux-dpdk/source/odp_init.c >> new file mode 100644 >> index 0000000..ecc2066 >> --- /dev/null >> +++ b/platform/linux-dpdk/source/odp_init.c >> @@ -0,0 +1,113 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include <odp_init.h> >> +#include <odp_internal.h> >> +#include <odp_debug.h> >> +#include <odp_packet_dpdk.h> >> + >> +int odp_init_dpdk(void) >> +{ >> + int test_argc = 5; >> + char *test_argv[6]; >> + int core_count, i, num_cores = 0; >> + char core_mask[8]; >> + >> + core_count = odp_sys_core_count(); >> + for (i = 0; i < core_count; i++) >> + num_cores += (0x1 << i); >> + sprintf(core_mask, "%x", num_cores); >> + >> + test_argv[0] = malloc(sizeof("odp_dpdk")); >> + strcpy(test_argv[0], "odp_dpdk"); >> + test_argv[1] = malloc(sizeof("-c")); >> + strcpy(test_argv[1], "-c"); >> + test_argv[2] = malloc(sizeof(core_mask)); >> + strcpy(test_argv[2], core_mask); >> + test_argv[3] = malloc(sizeof("-n")); >> + strcpy(test_argv[3], "-n"); >> + test_argv[4] = malloc(sizeof("3")); >> + strcpy(test_argv[4], "3"); >> + >> + if (rte_eal_init(test_argc, (char **)test_argv) < 0) { >> + ODP_ERR("Cannot init the Intel DPDK EAL!"); >> + return -1; >> + } >> + >> + if (rte_pmd_init_all() < 0) { >> + ODP_ERR("Cannot init pmd\n"); >> + return -1; >> + } >> + >> + if (rte_eal_pci_probe() < 0) { >> + ODP_ERR("Cannot probe PCI\n"); >> + return -1; >> + } >> + >> + return 0; >> +} >> + >> +int odp_init_global(void) >> +{ >> + odp_thread_init_global(); >> + >> + odp_system_info_init(); >> + >> + if (odp_init_dpdk()) { >> + ODP_ERR("ODP dpdk init failed.\n"); >> + return -1; >> + } >> + >> + if (odp_shm_init_global()) { >> + ODP_ERR("ODP shm init failed.\n"); >> + return -1; >> + } >> + >> + if (odp_buffer_pool_init_global()) { >> + ODP_ERR("ODP buffer pool init failed.\n"); >> + return -1; >> + } >> + >> + if (odp_queue_init_global()) { >> + ODP_ERR("ODP queue init failed.\n"); >> + return -1; >> + } >> + >> + if (odp_schedule_init_global()) { >> + ODP_ERR("ODP schedule init failed.\n"); >> + return -1; >> + } >> + >> + if (odp_pktio_init_global()) { >> + ODP_ERR("ODP packet io init failed.\n"); >> + return -1; >> + } >> + >> + if (odp_timer_init_global()) { >> + ODP_ERR("ODP timer init failed.\n"); >> + return -1; >> + } >> + >> + return 0; >> +} >> + >> + >> +int odp_init_local(int thr_id) >> +{ >> + odp_thread_init_local(thr_id); >> + >> + if (odp_pktio_init_local()) { >> + ODP_ERR("ODP packet io local init failed.\n"); >> + return -1; >> + } >> + >> + if (odp_schedule_init_local()) { >> + ODP_ERR("ODP schedule local init failed.\n"); >> + return -1; >> + } >> + >> + return 0; >> +} >> diff --git a/platform/linux-dpdk/source/odp_packet.c >> b/platform/linux-dpdk/source/odp_packet.c >> new file mode 100644 >> index 0000000..c34e626 >> --- /dev/null >> +++ b/platform/linux-dpdk/source/odp_packet.c >> @@ -0,0 +1,374 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include <odp_packet.h> >> +#include <odp_packet_internal.h> >> +#include <odp_hints.h> >> +#include <odp_byteorder.h> >> + >> +#include <helper/odp_eth.h> >> +#include <helper/odp_ip.h> >> + >> +#include <string.h> >> +#include <stdio.h> >> + >> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, >> odp_ipv4hdr_t *ipv4, >> + size_t *offset_out); >> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, >> odp_ipv6hdr_t *ipv6, >> + size_t *offset_out); >> + >> +void odp_packet_init(odp_packet_t pkt) >> +{ >> + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); >> + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, >> buf_hdr); >> + uint8_t *start; >> + size_t len; >> + >> + start = (uint8_t *)pkt_hdr + start_offset; >> + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; >> + memset(start, 0, len); >> + >> + pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >> + pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >> + pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >> +} >> + >> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf) >> +{ >> + return (odp_packet_t)buf; >> +} >> + >> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt) >> +{ >> + return (odp_buffer_t)pkt; >> +} >> + >> +void odp_packet_set_len(odp_packet_t pkt, size_t len) >> +{ >> + /* for rte_pktmbuf */ >> + odp_buffer_hdr_t *buf_hdr = >> odp_buf_to_hdr(odp_buffer_from_packet(pkt)); >> + buf_hdr->pkt.data_len = len; >> + >> + odp_packet_hdr(pkt)->frame_len = len; >> +} >> + >> +size_t odp_packet_get_len(odp_packet_t pkt) >> +{ >> + return odp_packet_hdr(pkt)->frame_len; >> +} >> + >> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt) >> +{ >> + return odp_buffer_addr(odp_buffer_from_packet(pkt)); >> +} >> + >> +uint8_t *odp_packet_start(odp_packet_t pkt) >> +{ >> + return odp_packet_buf_addr(pkt) + >> odp_packet_hdr(pkt)->frame_offset; >> +} >> + >> + >> +uint8_t *odp_packet_l2(odp_packet_t pkt) >> +{ >> + const size_t offset = odp_packet_l2_offset(pkt); >> + >> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >> + return NULL; >> + >> + return odp_packet_buf_addr(pkt) + offset; >> +} >> + >> +size_t odp_packet_l2_offset(odp_packet_t pkt) >> +{ >> + return odp_packet_hdr(pkt)->l2_offset; >> +} >> + >> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset) >> +{ >> + odp_packet_hdr(pkt)->l2_offset = offset; >> +} >> + >> +uint8_t *odp_packet_l3(odp_packet_t pkt) >> +{ >> + const size_t offset = odp_packet_l3_offset(pkt); >> + >> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >> + return NULL; >> + >> + return odp_packet_buf_addr(pkt) + offset; >> +} >> + >> +size_t odp_packet_l3_offset(odp_packet_t pkt) >> +{ >> + return odp_packet_hdr(pkt)->l3_offset; >> +} >> + >> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset) >> +{ >> + odp_packet_hdr(pkt)->l3_offset = offset; >> +} >> + >> +uint8_t *odp_packet_l4(odp_packet_t pkt) >> +{ >> + const size_t offset = odp_packet_l4_offset(pkt); >> + >> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >> + return NULL; >> + >> + return odp_packet_buf_addr(pkt) + offset; >> +} >> + >> +size_t odp_packet_l4_offset(odp_packet_t pkt) >> +{ >> + return odp_packet_hdr(pkt)->l4_offset; >> +} >> + >> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset) >> +{ >> + odp_packet_hdr(pkt)->l4_offset = offset; >> +} >> + >> +/** >> + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP >> + * >> + * Internal function: caller is resposible for passing only valid packet >> handles >> + * , lengths and offsets (usually done&called in packet input). >> + * >> + * @param pkt Packet handle >> + * @param len Packet length in bytes >> + * @param frame_offset Byte offset to L2 header >> + */ >> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset) >> +{ >> + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); >> + odp_ethhdr_t *eth; >> + odp_vlanhdr_t *vlan; >> + odp_ipv4hdr_t *ipv4; >> + odp_ipv6hdr_t *ipv6; >> + uint16_t ethtype; >> + size_t offset = 0; >> + uint8_t ip_proto = 0; >> + >> + pkt_hdr->input_flags.eth = 1; >> + pkt_hdr->frame_offset = frame_offset; >> + pkt_hdr->frame_len = len; >> + >> + if (odp_unlikely(len < ODP_ETH_LEN_MIN)) { >> + pkt_hdr->error_flags.frame_len = 1; >> + return; >> + } else if (len > ODP_ETH_LEN_MAX) { >> + pkt_hdr->input_flags.jumbo = 1; >> + } >> + >> + /* Assume valid L2 header, no CRC/FCS check in SW */ >> + pkt_hdr->input_flags.l2 = 1; >> + pkt_hdr->l2_offset = frame_offset; >> + >> + eth = (odp_ethhdr_t *)odp_packet_start(pkt); >> + ethtype = odp_be_to_cpu_16(eth->type); >> + vlan = (odp_vlanhdr_t *)ð->type; >> + >> + if (ethtype == ODP_ETHTYPE_VLAN_OUTER) { >> + pkt_hdr->input_flags.vlan_qinq = 1; >> + ethtype = odp_be_to_cpu_16(vlan->tpid); >> + offset += sizeof(odp_vlanhdr_t); >> + vlan = &vlan[1]; >> + } >> + >> + if (ethtype == ODP_ETHTYPE_VLAN) { >> + pkt_hdr->input_flags.vlan = 1; >> + ethtype = odp_be_to_cpu_16(vlan->tpid); >> + offset += sizeof(odp_vlanhdr_t); >> + } >> + >> + /* Set l3_offset+flag only for known ethtypes */ >> + switch (ethtype) { >> + case ODP_ETHTYPE_IPV4: >> + pkt_hdr->input_flags.ipv4 = 1; >> + pkt_hdr->input_flags.l3 = 1; >> + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + >> offset; >> + ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt); >> + ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset); >> + break; >> + case ODP_ETHTYPE_IPV6: >> + pkt_hdr->input_flags.ipv6 = 1; >> + pkt_hdr->input_flags.l3 = 1; >> + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + >> offset; >> + ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt); >> + ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset); >> + break; >> + case ODP_ETHTYPE_ARP: >> + pkt_hdr->input_flags.arp = 1; >> + /* fall through */ >> + default: >> + ip_proto = 0; >> + break; >> + } >> + >> + switch (ip_proto) { >> + case ODP_IPPROTO_UDP: >> + pkt_hdr->input_flags.udp = 1; >> + pkt_hdr->input_flags.l4 = 1; >> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >> + break; >> + case ODP_IPPROTO_TCP: >> + pkt_hdr->input_flags.tcp = 1; >> + pkt_hdr->input_flags.l4 = 1; >> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >> + break; >> + case ODP_IPPROTO_SCTP: >> + pkt_hdr->input_flags.sctp = 1; >> + pkt_hdr->input_flags.l4 = 1; >> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >> + break; >> + case ODP_IPPROTO_ICMP: >> + pkt_hdr->input_flags.icmp = 1; >> + pkt_hdr->input_flags.l4 = 1; >> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >> + break; >> + default: >> + /* 0 or unhandled IP protocols, don't set L4 flag+offset >> */ >> + if (pkt_hdr->input_flags.ipv6) { >> + /* IPv6 next_hdr is not L4, mark as IP-option >> instead */ >> + pkt_hdr->input_flags.ipopt = 1; >> + } >> + break; >> + } >> +} >> + >> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, >> odp_ipv4hdr_t *ipv4, >> + size_t *offset_out) >> +{ >> + uint8_t ihl; >> + uint16_t frag_offset; >> + >> + ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl); >> + if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) { >> + pkt_hdr->error_flags.ip_err = 1; >> + return 0; >> + } >> + >> + if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) { >> + pkt_hdr->input_flags.ipopt = 1; >> + return 0; >> + } >> + >> + /* A packet is a fragment if: >> + * "more fragments" flag is set (all fragments except the last) >> + * OR >> + * "fragment offset" field is nonzero (all fragments except the >> first) >> + */ >> + frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); >> + if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) { >> + pkt_hdr->input_flags.ipfrag = 1; >> + return 0; >> + } >> + >> + if (ipv4->proto == ODP_IPPROTO_ESP || >> + ipv4->proto == ODP_IPPROTO_AH) { >> + pkt_hdr->input_flags.ipsec = 1; >> + return 0; >> + } >> + >> + /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after >> return */ >> + >> + *offset_out = sizeof(uint32_t) * ihl; >> + return ipv4->proto; >> +} >> + >> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, >> odp_ipv6hdr_t *ipv6, >> + size_t *offset_out) >> +{ >> + if (ipv6->next_hdr == ODP_IPPROTO_ESP || >> + ipv6->next_hdr == ODP_IPPROTO_AH) { >> + pkt_hdr->input_flags.ipopt = 1; >> + pkt_hdr->input_flags.ipsec = 1; >> + return 0; >> + } >> + >> + if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) { >> + pkt_hdr->input_flags.ipopt = 1; >> + pkt_hdr->input_flags.ipfrag = 1; >> + return 0; >> + } >> + >> + /* Don't step through more extensions */ >> + *offset_out = ODP_IPV6HDR_LEN; >> + return ipv6->next_hdr; >> +} >> + >> +void odp_packet_print(odp_packet_t pkt) >> +{ >> + int max_len = 512; >> + char str[max_len]; >> + int len = 0; >> + int n = max_len-1; >> + odp_packet_hdr_t *hdr = odp_packet_hdr(pkt); >> + >> + len += snprintf(&str[len], n-len, "Packet "); >> + len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt); >> + len += snprintf(&str[len], n-len, >> + " input_flags 0x%x\n", hdr->input_flags.all); >> + len += snprintf(&str[len], n-len, >> + " error_flags 0x%x\n", hdr->error_flags.all); >> + len += snprintf(&str[len], n-len, >> + " output_flags 0x%x\n", hdr->output_flags.all); >> + len += snprintf(&str[len], n-len, >> + " frame_offset %u\n", hdr->frame_offset); >> + len += snprintf(&str[len], n-len, >> + " l2_offset %u\n", hdr->l2_offset); >> + len += snprintf(&str[len], n-len, >> + " l3_offset %u\n", hdr->l3_offset); >> + len += snprintf(&str[len], n-len, >> + " l4_offset %u\n", hdr->l4_offset); >> + len += snprintf(&str[len], n-len, >> + " frame_len %u\n", hdr->frame_len); >> + len += snprintf(&str[len], n-len, >> + " input %u\n", hdr->input); >> + str[len] = '\0'; >> + >> + printf("\n%s\n", str); >> +} >> + >> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src) >> +{ >> + odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst); >> + odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src); >> + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, >> buf_hdr); >> + uint8_t *start_src; >> + uint8_t *start_dst; >> + size_t len; >> + >> + if (pkt_dst == ODP_PACKET_INVALID || pkt_src == >> ODP_PACKET_INVALID) >> + return -1; >> + >> + /* if (pkt_hdr_dst->buf_hdr.size < */ >> + /* pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */ >> + if (pkt_hdr_dst->buf_hdr.buf_len < >> + pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) >> + return -1; >> + >> + /* Copy packet header */ >> + start_dst = (uint8_t *)pkt_hdr_dst + start_offset; >> + start_src = (uint8_t *)pkt_hdr_src + start_offset; >> + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; >> + memcpy(start_dst, start_src, len); >> + >> + /* Copy frame payload */ >> + start_dst = (uint8_t *)odp_packet_start(pkt_dst); >> + start_src = (uint8_t *)odp_packet_start(pkt_src); >> + len = pkt_hdr_src->frame_len; >> + memcpy(start_dst, start_src, len); >> + >> + /* Copy useful things from the buffer header */ >> + /* pkt_hdr_dst->buf_hdr.cur_offset = >> pkt_hdr_src->buf_hdr.cur_offset; */ >> + >> + /* Create a copy of the scatter list */ >> + /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */ >> + /* odp_buffer_from_packet(pkt_src)); */ >> + >> + return 0; >> +} >> diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c >> b/platform/linux-dpdk/source/odp_packet_dpdk.c >> new file mode 100644 >> index 0000000..6d16bbe >> --- /dev/null >> +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c >> @@ -0,0 +1,177 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#define _GNU_SOURCE >> +#include <stdio.h> >> +#include <errno.h> >> +#include <sys/types.h> >> +#include <sys/stat.h> >> +#include <sys/ioctl.h> >> +#include <sys/mman.h> >> +#include <poll.h> >> +#include <unistd.h> >> +#include <fcntl.h> >> +#include <string.h> >> +#include <stdlib.h> >> + >> +#include <linux/ethtool.h> >> +#include <linux/sockios.h> >> + >> +#include <odp_hints.h> >> +#include <odp_thread.h> >> + >> +#include <odp_packet_dpdk.h> >> +#include <net/if.h> >> + >> +/* >> + * RX and TX Prefetch, Host, and Write-back threshold values should be >> + * carefully set for optimal performance. Consult the network >> + * controller's datasheet and supporting DPDK documentation for guidance >> + * on how these parameters should be set. >> + */ >> +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ >> +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ >> +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. >> */ >> + >> +/* >> + * These default values are optimized for use with the Intel(R) 82599 10 >> GbE >> + * Controller and the DPDK ixgbe PMD. Consider using other values for >> other >> + * network controllers and/or network drivers. >> + */ >> +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. >> */ >> +#define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ >> +#define TX_WTHRESH 0 /**< Default values of TX write-back threshold >> reg. */ >> + >> +#define MAX_PKT_BURST 32 >> +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ >> +#define RTE_TEST_RX_DESC_DEFAULT 128 >> +#define RTE_TEST_TX_DESC_DEFAULT 512 >> +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; >> +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; >> + >> +static const struct rte_eth_conf port_conf = { >> + .rxmode = { >> + .split_hdr_size = 0, >> + .header_split = 0, /**< Header Split disabled */ >> + .hw_ip_checksum = 0, /**< IP checksum offload disabled */ >> + .hw_vlan_filter = 0, /**< VLAN filtering disabled */ >> + .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ >> + .hw_strip_crc = 0, /**< CRC stripped by hardware */ >> + }, >> + .txmode = { >> + .mq_mode = ETH_MQ_TX_NONE, >> + }, >> +}; >> + >> +static const struct rte_eth_rxconf rx_conf = { >> + .rx_thresh = { >> + .pthresh = RX_PTHRESH, >> + .hthresh = RX_HTHRESH, >> + .wthresh = RX_WTHRESH, >> + }, >> +}; >> + >> +static const struct rte_eth_txconf tx_conf = { >> + .tx_thresh = { >> + .pthresh = TX_PTHRESH, >> + .hthresh = TX_HTHRESH, >> + .wthresh = TX_WTHRESH, >> + }, >> + .tx_free_thresh = 0, /* Use PMD default values */ >> + .tx_rs_thresh = 0, /* Use PMD default values */ >> + /* >> + * As the example won't handle mult-segments and offload cases, >> + * set the flag by default. >> + */ >> + .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, >> +}; >> + >> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, >> + odp_buffer_pool_t pool) >> +{ >> + ODP_DBG("setup_pkt_dpdk\n"); >> + >> + static struct ether_addr eth_addr[RTE_MAX_ETHPORTS]; >> + uint8_t portid = 0; >> + uint16_t queueid = 0; >> + int ret; >> + printf("vincent netdev: %s\n", netdev); >> + printf("vincent pool: %lx\n", pool); >> + >> + portid = atoi(netdev); >> + pkt_dpdk->portid = portid; >> + pkt_dpdk->queueid = queueid; >> + pkt_dpdk->pool = pool; >> + printf("vincent portid: %u\n", portid); >> + >> + fflush(stdout); >> + ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); >> + if (ret < 0) >> + ODP_ERR("Cannot configure device: err=%d, port=%u\n", >> + ret, (unsigned) portid); >> + >> + rte_eth_macaddr_get(portid, ð_addr[portid]); >> + ODP_DBG("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", >> + (unsigned) portid, >> + eth_addr[portid].addr_bytes[0], >> + eth_addr[portid].addr_bytes[1], >> + eth_addr[portid].addr_bytes[2], >> + eth_addr[portid].addr_bytes[3], >> + eth_addr[portid].addr_bytes[4], >> + eth_addr[portid].addr_bytes[5]); >> + >> + /* init one RX queue on each port */ >> + fflush(stdout); >> + ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, >> + rte_eth_dev_socket_id(portid), >> &rx_conf, >> + (struct rte_mempool *)pool); >> + if (ret < 0) >> + ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n", >> + ret, (unsigned) portid); >> + ODP_DBG("dpdk rx queue setup done\n"); >> + >> + /* init one TX queue on each port */ >> + fflush(stdout); >> + ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, >> + rte_eth_dev_socket_id(portid), &tx_conf); >> + if (ret < 0) >> + ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n", >> + ret, (unsigned) portid); >> + ODP_DBG("dpdk tx queue setup done\n"); >> + >> + /* Start device */ >> + ret = rte_eth_dev_start(portid); >> + if (ret < 0) >> + ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n", >> + ret, (unsigned) portid); >> + ODP_DBG("dpdk setup done\n\n"); >> + >> + >> + return 0; >> +} >> + >> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk) >> +{ >> + ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid); >> + >> + return 0; >> +} >> + >> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], >> + unsigned len) >> +{ >> + return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid, >> + (uint16_t)pkt_dpdk->queueid, >> + (struct rte_mbuf **)pkt_table, >> (uint16_t)len); >> +} >> + >> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], >> + unsigned len) >> +{ >> + return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid, >> + (uint16_t)pkt_dpdk->queueid, >> + (struct rte_mbuf **)pkt_table, >> (uint16_t)len); >> +} >> diff --git a/platform/linux-dpdk/source/odp_packet_io.c >> b/platform/linux-dpdk/source/odp_packet_io.c >> new file mode 100644 >> index 0000000..abea0ec >> --- /dev/null >> +++ b/platform/linux-dpdk/source/odp_packet_io.c >> @@ -0,0 +1,561 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include <odp_packet_io.h> >> +#include <odp_packet_io_internal.h> >> +#include <odp_packet_io_queue.h> >> +#include <odp_packet.h> >> +#include <odp_packet_internal.h> >> +#include <odp_internal.h> >> +#include <odp_spinlock.h> >> +#include <odp_shared_memory.h> >> +#include <odp_packet_socket.h> >> +#ifdef ODP_HAVE_NETMAP >> +#include <odp_packet_netmap.h> >> +#endif >> +#include <odp_hints.h> >> +#include <odp_config.h> >> +#include <odp_queue_internal.h> >> +#include <odp_schedule_internal.h> >> +#include <odp_debug.h> >> + >> +#include <odp_pktio_socket.h> >> +#ifdef ODP_HAVE_NETMAP >> +#include <odp_pktio_netmap.h> >> +#endif >> + >> +#include <string.h> >> + >> +typedef struct { >> + pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES]; >> +} pktio_table_t; >> + >> +static pktio_table_t *pktio_tbl; >> + >> + >> +static pktio_entry_t *get_entry(odp_pktio_t id) >> +{ >> + if (odp_unlikely(id == ODP_PKTIO_INVALID || >> + id > ODP_CONFIG_PKTIO_ENTRIES)) >> + return NULL; >> + >> + return &pktio_tbl->entries[id - 1]; >> +} >> + >> +int odp_pktio_init_global(void) >> +{ >> + char name[ODP_QUEUE_NAME_LEN]; >> + pktio_entry_t *pktio_entry; >> + queue_entry_t *queue_entry; >> + odp_queue_t qid; >> + int id; >> + >> + pktio_tbl = odp_shm_reserve("odp_pktio_entries", >> + sizeof(pktio_table_t), >> + sizeof(pktio_entry_t)); >> + if (pktio_tbl == NULL) >> + return -1; >> + >> + memset(pktio_tbl, 0, sizeof(pktio_table_t)); >> + >> + for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) { >> + pktio_entry = get_entry(id); >> + >> + odp_spinlock_init(&pktio_entry->s.lock); >> + >> + /* Create a default output queue for each pktio resource >> */ >> + snprintf(name, sizeof(name), "%i-pktio_outq_default", >> (int)id); >> + name[ODP_QUEUE_NAME_LEN-1] = '\0'; >> + >> + qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, NULL); >> + if (qid == ODP_QUEUE_INVALID) >> + return -1; >> + pktio_entry->s.outq_default = qid; >> + >> + queue_entry = queue_to_qentry(qid); >> + queue_entry->s.pktout = id; >> + } >> + >> + return 0; >> +} >> + >> +int odp_pktio_init_local(void) >> +{ >> + return 0; >> +} >> + >> +static int is_free(pktio_entry_t *entry) >> +{ >> + return (entry->s.taken == 0); >> +} >> + >> +static void set_free(pktio_entry_t *entry) >> +{ >> + entry->s.taken = 0; >> +} >> + >> +static void set_taken(pktio_entry_t *entry) >> +{ >> + entry->s.taken = 1; >> +} >> + >> +static void lock_entry(pktio_entry_t *entry) >> +{ >> + odp_spinlock_lock(&entry->s.lock); >> +} >> + >> +static void unlock_entry(pktio_entry_t *entry) >> +{ >> + odp_spinlock_unlock(&entry->s.lock); >> +} >> + >> +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t >> *params) >> +{ >> + set_taken(entry); >> + entry->s.inq_default = ODP_QUEUE_INVALID; >> + switch (params->type) { >> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >> + memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock)); >> + memset(&entry->s.pkt_sock_mmap, 0, >> + sizeof(entry->s.pkt_sock_mmap)); >> + break; >> +#ifdef ODP_HAVE_NETMAP >> + case ODP_PKTIO_TYPE_NETMAP: >> + memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm)); >> + break; >> +#endif >> + case ODP_PKTIO_TYPE_DPDK: >> + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); >> + break; >> + default: >> + ODP_ERR("Packet I/O type not supported. Please >> recompile\n"); >> + break; >> + } >> + /* Save pktio parameters, type is the most useful */ >> + memcpy(&entry->s.params, params, sizeof(*params)); >> +} >> + >> +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params) >> +{ >> + odp_pktio_t id; >> + pktio_entry_t *entry; >> + int i; >> + >> + for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) { >> + entry = &pktio_tbl->entries[i]; >> + if (is_free(entry)) { >> + lock_entry(entry); >> + if (is_free(entry)) { >> + init_pktio_entry(entry, params); >> + id = i + 1; >> + return id; /* return with entry locked! */ >> + } >> + unlock_entry(entry); >> + } >> + } >> + >> + return ODP_PKTIO_INVALID; >> +} >> + >> +static int free_pktio_entry(odp_pktio_t id) >> +{ >> + pktio_entry_t *entry = get_entry(id); >> + >> + if (entry == NULL) >> + return -1; >> + >> + set_free(entry); >> + >> + return 0; >> +} >> + >> +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool, >> + odp_pktio_params_t *params) >> +{ >> + odp_pktio_t id; >> + pktio_entry_t *pktio_entry; >> + int res; >> + >> + if (params == NULL) { >> + ODP_ERR("Invalid pktio params\n"); >> + return ODP_PKTIO_INVALID; >> + } >> + >> + switch (params->type) { >> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >> + ODP_DBG("Allocating socket pktio\n"); >> + break; >> +#ifdef ODP_HAVE_NETMAP >> + case ODP_PKTIO_TYPE_NETMAP: >> + ODP_DBG("Allocating netmap pktio\n"); >> + break; >> +#endif >> + case ODP_PKTIO_TYPE_DPDK: >> + ODP_DBG("Allocating dpdk pktio\n"); >> + break; >> + default: >> + ODP_ERR("Invalid pktio type: %02x\n", params->type); >> + return ODP_PKTIO_INVALID; >> + } >> + >> + id = alloc_lock_pktio_entry(params); >> + if (id == ODP_PKTIO_INVALID) { >> + ODP_ERR("No resources available.\n"); >> + return ODP_PKTIO_INVALID; >> + } >> + /* if successful, alloc_pktio_entry() returns with the entry >> locked */ >> + >> + pktio_entry = get_entry(id); >> + >> + switch (params->type) { >> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >> + res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, pool); >> + if (res == -1) { >> + close_pkt_sock(&pktio_entry->s.pkt_sock); >> + free_pktio_entry(id); >> + id = ODP_PKTIO_INVALID; >> + } >> + break; >> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >> + res = setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, >> dev, >> + pool, params->sock_params.fanout); >> + if (res == -1) { >> + >> close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap); >> + free_pktio_entry(id); >> + id = ODP_PKTIO_INVALID; >> + } >> + break; >> +#ifdef ODP_HAVE_NETMAP >> + case ODP_PKTIO_TYPE_NETMAP: >> + >> + res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev, >> + pool, ¶ms->nm_params); >> + if (res == -1) { >> + close_pkt_netmap(&pktio_entry->s.pkt_nm); >> + free_pktio_entry(id); >> + id = ODP_PKTIO_INVALID; >> + } >> + break; >> +#endif >> + case ODP_PKTIO_TYPE_DPDK: >> + res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, pool); >> + if (res == -1) { >> + close_pkt_dpdk(&pktio_entry->s.pkt_dpdk); >> + free_pktio_entry(id); >> + id = ODP_PKTIO_INVALID; >> + } >> + break; >> + default: >> + free_pktio_entry(id); >> + id = ODP_PKTIO_INVALID; >> + ODP_ERR("Invalid pktio type. Please recompile.\n"); >> + break; >> + } >> + >> + unlock_entry(pktio_entry); >> + return id; >> +} >> + >> +int odp_pktio_close(odp_pktio_t id) >> +{ >> + pktio_entry_t *entry; >> + int res = -1; >> + >> + entry = get_entry(id); >> + if (entry == NULL) >> + return -1; >> + >> + lock_entry(entry); >> + if (!is_free(entry)) { >> + switch (entry->s.params.type) { >> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >> + res = close_pkt_sock(&entry->s.pkt_sock); >> + break; >> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >> + res = >> close_pkt_sock_mmap(&entry->s.pkt_sock_mmap); >> + break; >> +#ifdef ODP_HAVE_NETMAP >> + case ODP_PKTIO_TYPE_NETMAP: >> + res = close_pkt_netmap(&entry->s.pkt_nm); >> + break; >> +#endif >> + case ODP_PKTIO_TYPE_DPDK: >> + res = close_pkt_dpdk(&entry->s.pkt_dpdk); >> + break; >> + default: >> + break; >> + res |= free_pktio_entry(id); >> + } >> + } >> + unlock_entry(entry); >> + >> + if (res != 0) >> + return -1; >> + >> + return 0; >> +} >> + >> +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio) >> +{ >> + odp_packet_hdr(pkt)->input = pktio; >> +} >> + >> +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt) >> +{ >> + return odp_packet_hdr(pkt)->input; >> +} >> + >> +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned >> len) >> +{ >> + pktio_entry_t *pktio_entry = get_entry(id); >> + int pkts; >> + int i; >> + >> + if (pktio_entry == NULL) >> + return -1; >> + >> + lock_entry(pktio_entry); >> + switch (pktio_entry->s.params.type) { >> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >> + pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock, >> + pkt_table, len); >> + break; >> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >> + pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, >> + pkt_table, len); >> + break; >> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >> + pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, >> + pkt_table, len); >> + break; >> +#ifdef ODP_HAVE_NETMAP >> + case ODP_PKTIO_TYPE_NETMAP: >> + pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm, pkt_table, >> len); >> + break; >> +#endif >> + case ODP_PKTIO_TYPE_DPDK: >> + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, >> len); >> + break; >> + default: >> + pkts = -1; >> + break; >> + } >> + >> + unlock_entry(pktio_entry); >> + if (pkts < 0) >> + return pkts; >> + >> + for (i = 0; i < pkts; ++i) >> + odp_pktio_set_input(pkt_table[i], id); >> + >> + return pkts; >> +} >> + >> +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned >> len) >> +{ >> + pktio_entry_t *pktio_entry = get_entry(id); >> + int pkts; >> + >> + if (pktio_entry == NULL) >> + return -1; >> + >> + lock_entry(pktio_entry); >> + switch (pktio_entry->s.params.type) { >> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >> + pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock, >> + pkt_table, len); >> + break; >> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >> + pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, >> + pkt_table, len); >> + break; >> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >> + pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, >> + pkt_table, len); >> + break; >> +#ifdef ODP_HAVE_NETMAP >> + case ODP_PKTIO_TYPE_NETMAP: >> + pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm, >> + pkt_table, len); >> + break; >> +#endif >> + case ODP_PKTIO_TYPE_DPDK: >> + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, >> + pkt_table, len); >> + break; >> + default: >> + pkts = -1; >> + } >> + unlock_entry(pktio_entry); >> + >> + return pkts; >> +} >> + >> +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue) >> +{ >> + pktio_entry_t *pktio_entry = get_entry(id); >> + queue_entry_t *qentry = queue_to_qentry(queue); >> + >> + if (pktio_entry == NULL || qentry == NULL) >> + return -1; >> + >> + if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN) >> + return -1; >> + >> + lock_entry(pktio_entry); >> + pktio_entry->s.inq_default = queue; >> + unlock_entry(pktio_entry); >> + >> + queue_lock(qentry); >> + qentry->s.pktin = id; >> + qentry->s.status = QUEUE_STATUS_SCHED; >> + queue_unlock(qentry); >> + >> + odp_schedule_queue(queue, qentry->s.param.sched.prio); >> + >> + return 0; >> +} >> + >> +int odp_pktio_inq_remdef(odp_pktio_t id) >> +{ >> + return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID); >> +} >> + >> +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id) >> +{ >> + pktio_entry_t *pktio_entry = get_entry(id); >> + >> + if (pktio_entry == NULL) >> + return ODP_QUEUE_INVALID; >> + >> + return pktio_entry->s.inq_default; >> +} >> + >> +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id) >> +{ >> + pktio_entry_t *pktio_entry = get_entry(id); >> + >> + if (pktio_entry == NULL) >> + return ODP_QUEUE_INVALID; >> + >> + return pktio_entry->s.outq_default; >> +} >> + >> +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) >> +{ >> + odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t) buf_hdr); >> + int len = 1; >> + int nbr; >> + >> + nbr = odp_pktio_send(qentry->s.pktout, &pkt, len); >> + return (nbr == len ? 0 : -1); >> +} >> + >> +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry) >> +{ >> + (void)qentry; >> + return NULL; >> +} >> + >> +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], >> + int num) >> +{ >> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >> + int nbr; >> + int i; >> + >> + for (i = 0; i < num; ++i) >> + pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t) >> buf_hdr[i]); >> + >> + nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num); >> + return (nbr == num ? 0 : -1); >> +} >> + >> +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], >> + int num) >> +{ >> + (void)qentry; >> + (void)buf_hdr; >> + (void)num; >> + >> + return 0; >> +} >> + >> +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) >> +{ >> + /* Use default action */ >> + return queue_enq(qentry, buf_hdr); >> +} >> + >> +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry) >> +{ >> + odp_buffer_hdr_t *buf_hdr; >> + >> + buf_hdr = queue_deq(qentry); >> + >> + if (buf_hdr == NULL) { >> + odp_packet_t pkt; >> + odp_buffer_t buf; >> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >> + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; >> + int pkts, i, j; >> + >> + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, >> + QUEUE_MULTI_MAX); >> + >> + if (pkts > 0) { >> + pkt = pkt_tbl[0]; >> + buf = odp_buffer_from_packet(pkt); >> + buf_hdr = odp_buf_to_hdr(buf); >> + >> + for (i = 1, j = 0; i < pkts; ++i) { >> + buf = odp_buffer_from_packet(pkt_tbl[i]); >> + tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf); >> + } >> + queue_enq_multi(qentry, tmp_hdr_tbl, j); >> + } >> + } >> + >> + return buf_hdr; >> +} >> + >> +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], >> int num) >> +{ >> + /* Use default action */ >> + return queue_enq_multi(qentry, buf_hdr, num); >> +} >> + >> +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], >> int num) >> +{ >> + int nbr; >> + >> + nbr = queue_deq_multi(qentry, buf_hdr, num); >> + >> + if (nbr < num) { >> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >> + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; >> + odp_buffer_t buf; >> + int pkts, i; >> + >> + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, >> + QUEUE_MULTI_MAX); >> + if (pkts > 0) { >> + for (i = 0; i < pkts; ++i) { >> + buf = odp_buffer_from_packet(pkt_tbl[i]); >> + tmp_hdr_tbl[i] = odp_buf_to_hdr(buf); >> + } >> + queue_enq_multi(qentry, tmp_hdr_tbl, pkts); >> + } >> + } >> + >> + return nbr; >> +} >> diff --git a/platform/linux-dpdk/source/odp_queue.c >> b/platform/linux-dpdk/source/odp_queue.c >> new file mode 100644 >> index 0000000..554b8ea >> --- /dev/null >> +++ b/platform/linux-dpdk/source/odp_queue.c >> @@ -0,0 +1,435 @@ >> +/* Copyright (c) 2013, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include <odp_queue.h> >> +#include <odp_queue_internal.h> >> +#include <odp_std_types.h> >> +#include <odp_align.h> >> +#include <odp_buffer.h> >> +#include <odp_buffer_internal.h> >> +#include <odp_buffer_pool_internal.h> >> +#include <odp_internal.h> >> +#include <odp_shared_memory.h> >> +#include <odp_schedule_internal.h> >> +#include <odp_config.h> >> +#include <odp_packet_io_internal.h> >> +#include <odp_packet_io_queue.h> >> +#include <odp_debug.h> >> +#include <odp_hints.h> >> + >> +#ifdef USE_TICKETLOCK >> +#include <odp_ticketlock.h> >> +#define LOCK(a) odp_ticketlock_lock(a) >> +#define UNLOCK(a) odp_ticketlock_unlock(a) >> +#define LOCK_INIT(a) odp_ticketlock_init(a) >> +#else >> +#include <odp_spinlock.h> >> +#define LOCK(a) odp_spinlock_lock(a) >> +#define UNLOCK(a) odp_spinlock_unlock(a) >> +#define LOCK_INIT(a) odp_spinlock_init(a) >> +#endif >> + >> +#include <string.h> >> + >> + >> +typedef struct queue_table_t { >> + queue_entry_t queue[ODP_CONFIG_QUEUES]; >> +} queue_table_t; >> + >> +static queue_table_t *queue_tbl; >> + >> + >> +queue_entry_t *get_qentry(uint32_t queue_id) >> +{ >> + return &queue_tbl->queue[queue_id]; >> +} >> + >> +static void queue_init(queue_entry_t *queue, const char *name, >> + odp_queue_type_t type, odp_queue_param_t *param) >> +{ >> + strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1); >> + queue->s.type = type; >> + >> + if (param) { >> + memcpy(&queue->s.param, param, sizeof(odp_queue_param_t)); >> + } else { >> + /* Defaults */ >> + memset(&queue->s.param, 0, sizeof(odp_queue_param_t)); >> + queue->s.param.sched.prio = ODP_SCHED_PRIO_DEFAULT; >> + queue->s.param.sched.sync = ODP_SCHED_SYNC_DEFAULT; >> + queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT; >> + } >> + >> + switch (type) { >> + case ODP_QUEUE_TYPE_PKTIN: >> + queue->s.enqueue = pktin_enqueue; >> + queue->s.dequeue = pktin_dequeue; >> + queue->s.enqueue_multi = pktin_enq_multi; >> + queue->s.dequeue_multi = pktin_deq_multi; >> + break; >> + case ODP_QUEUE_TYPE_PKTOUT: >> + queue->s.enqueue = pktout_enqueue; >> + queue->s.dequeue = pktout_dequeue; >> + queue->s.enqueue_multi = pktout_enq_multi; >> + queue->s.dequeue_multi = pktout_deq_multi; >> + break; >> + default: >> + queue->s.enqueue = queue_enq; >> + queue->s.dequeue = queue_deq; >> + queue->s.enqueue_multi = queue_enq_multi; >> + queue->s.dequeue_multi = queue_deq_multi; >> + break; >> + } >> + >> + queue->s.head = NULL; >> + queue->s.tail = NULL; >> + queue->s.sched_buf = ODP_BUFFER_INVALID; >> +} >> + >> + >> +int odp_queue_init_global(void) >> +{ >> + uint32_t i; >> + >> + ODP_DBG("Queue init ... "); >> + >> + queue_tbl = odp_shm_reserve("odp_queues", >> + sizeof(queue_table_t), >> + sizeof(queue_entry_t)); >> + >> + if (queue_tbl == NULL) >> + return -1; >> + >> + memset(queue_tbl, 0, sizeof(queue_table_t)); >> + >> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >> + /* init locks */ >> + queue_entry_t *queue = get_qentry(i); >> + LOCK_INIT(&queue->s.lock); >> + queue->s.handle = queue_from_id(i); >> + } >> + >> + ODP_DBG("done\n"); >> + ODP_DBG("Queue init global\n"); >> + ODP_DBG(" struct queue_entry_s size %zu\n", >> + sizeof(struct queue_entry_s)); >> + ODP_DBG(" queue_entry_t size %zu\n", >> + sizeof(queue_entry_t)); >> + ODP_DBG("\n"); >> + >> + return 0; >> +} >> + >> +odp_queue_type_t odp_queue_type(odp_queue_t handle) >> +{ >> + queue_entry_t *queue; >> + >> + queue = queue_to_qentry(handle); >> + >> + return queue->s.type; >> +} >> + >> +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle) >> +{ >> + queue_entry_t *queue; >> + >> + queue = queue_to_qentry(handle); >> + >> + return queue->s.param.sched.sync; >> +} >> + >> +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type, >> + odp_queue_param_t *param) >> +{ >> + uint32_t i; >> + queue_entry_t *queue; >> + odp_queue_t handle = ODP_QUEUE_INVALID; >> + >> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >> + queue = &queue_tbl->queue[i]; >> + >> + if (queue->s.status != QUEUE_STATUS_FREE) >> + continue; >> + >> + LOCK(&queue->s.lock); >> + if (queue->s.status == QUEUE_STATUS_FREE) { >> + queue_init(queue, name, type, param); >> + >> + if (type == ODP_QUEUE_TYPE_SCHED || >> + type == ODP_QUEUE_TYPE_PKTIN) >> + queue->s.status = QUEUE_STATUS_NOTSCHED; >> + else >> + queue->s.status = QUEUE_STATUS_READY; >> + >> + handle = queue->s.handle; >> + UNLOCK(&queue->s.lock); >> + break; >> + } >> + UNLOCK(&queue->s.lock); >> + } >> + >> + if (handle != ODP_QUEUE_INVALID && >> + (type == ODP_QUEUE_TYPE_SCHED || type == >> ODP_QUEUE_TYPE_PKTIN)) { >> + odp_buffer_t buf; >> + >> + buf = odp_schedule_buffer_alloc(handle); >> + if (buf == ODP_BUFFER_INVALID) { >> + ODP_ERR("queue_init: sched buf alloc failed\n"); >> + return ODP_QUEUE_INVALID; >> + } >> + >> + queue->s.sched_buf = buf; >> + odp_schedule_mask_set(handle, queue->s.param.sched.prio); >> + } >> + >> + return handle; >> +} >> + >> + >> +odp_buffer_t queue_sched_buf(odp_queue_t handle) >> +{ >> + queue_entry_t *queue; >> + queue = queue_to_qentry(handle); >> + >> + return queue->s.sched_buf; >> +} >> + >> + >> +int queue_sched_atomic(odp_queue_t handle) >> +{ >> + queue_entry_t *queue; >> + queue = queue_to_qentry(handle); >> + >> + return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC; >> +} >> + >> + >> +odp_queue_t odp_queue_lookup(const char *name) >> +{ >> + uint32_t i; >> + >> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >> + queue_entry_t *queue = &queue_tbl->queue[i]; >> + >> + if (queue->s.status == QUEUE_STATUS_FREE) >> + continue; >> + >> + LOCK(&queue->s.lock); >> + if (strcmp(name, queue->s.name) == 0) { >> + /* found it */ >> + UNLOCK(&queue->s.lock); >> + return queue->s.handle; >> + } >> + UNLOCK(&queue->s.lock); >> + } >> + >> + return ODP_QUEUE_INVALID; >> +} >> + >> + >> +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr) >> +{ >> + int sched = 0; >> + >> + LOCK(&queue->s.lock); >> + if (queue->s.head == NULL) { >> + /* Empty queue */ >> + queue->s.head = buf_hdr; >> + queue->s.tail = buf_hdr; >> + buf_hdr->pkt.next = NULL; >> + } else { >> + queue->s.tail->pkt.next = buf_hdr; >> + queue->s.tail = buf_hdr; >> + buf_hdr->pkt.next = NULL; >> + } >> + >> + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { >> + queue->s.status = QUEUE_STATUS_SCHED; >> + sched = 1; /* retval: schedule queue */ >> + } >> + UNLOCK(&queue->s.lock); >> + >> + /* Add queue to scheduling */ >> + if (sched == 1) >> + odp_schedule_queue(queue->s.handle, >> queue->s.param.sched.prio); >> + >> + return 0; >> +} >> + >> + >> +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], >> int num) >> +{ >> + int sched = 0; >> + int i; >> + odp_buffer_hdr_t *tail; >> + >> + for (i = 0; i < num - 1; i++) >> + buf_hdr[i]->pkt.next = buf_hdr[i+1]; >> + >> + tail = buf_hdr[num-1]; >> + buf_hdr[num-1]->pkt.next = NULL; >> + >> + LOCK(&queue->s.lock); >> + /* Empty queue */ >> + if (queue->s.head == NULL) >> + queue->s.head = buf_hdr[0]; >> + else >> + queue->s.tail->pkt.next = buf_hdr[0]; >> + >> + queue->s.tail = tail; >> + >> + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { >> + queue->s.status = QUEUE_STATUS_SCHED; >> + sched = 1; /* retval: schedule queue */ >> + } >> + UNLOCK(&queue->s.lock); >> + >> + /* Add queue to scheduling */ >> + if (sched == 1) >> + odp_schedule_queue(queue->s.handle, >> queue->s.param.sched.prio); >> + >> + return 0; >> +} >> + >> + >> +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int num) >> +{ >> + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; >> + queue_entry_t *queue; >> + int i; >> + >> + if (num > QUEUE_MULTI_MAX) >> + num = QUEUE_MULTI_MAX; >> + >> + queue = queue_to_qentry(handle); >> + >> + for (i = 0; i < num; i++) >> + buf_hdr[i] = odp_buf_to_hdr(buf[i]); >> + >> + return queue->s.enqueue_multi(queue, buf_hdr, num); >> +} >> + >> + >> +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf) >> +{ >> + odp_buffer_hdr_t *buf_hdr; >> + queue_entry_t *queue; >> + >> + queue = queue_to_qentry(handle); >> + buf_hdr = odp_buf_to_hdr(buf); >> + >> + return queue->s.enqueue(queue, buf_hdr); >> +} >> + >> + >> +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue) >> +{ >> + odp_buffer_hdr_t *buf_hdr = NULL; >> + >> + LOCK(&queue->s.lock); >> + >> + if (queue->s.head == NULL) { >> + /* Already empty queue */ >> + if (queue->s.status == QUEUE_STATUS_SCHED && >> + queue->s.type != ODP_QUEUE_TYPE_PKTIN) >> + queue->s.status = QUEUE_STATUS_NOTSCHED; >> + } else { >> + buf_hdr = queue->s.head; >> + queue->s.head = buf_hdr->pkt.next; >> + buf_hdr->pkt.next = NULL; >> + >> + if (queue->s.head == NULL) { >> + /* Queue is now empty */ >> + queue->s.tail = NULL; >> + } >> + } >> + >> + UNLOCK(&queue->s.lock); >> + >> + return buf_hdr; >> +} >> + >> + >> +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], >> int num) >> +{ >> + int i = 0; >> + >> + LOCK(&queue->s.lock); >> + >> + if (queue->s.head == NULL) { >> + /* Already empty queue */ >> + if (queue->s.status == QUEUE_STATUS_SCHED && >> + queue->s.type != ODP_QUEUE_TYPE_PKTIN) >> + queue->s.status = QUEUE_STATUS_NOTSCHED; >> + } else { >> + odp_buffer_hdr_t *hdr = queue->s.head; >> + >> + for (; i < num && hdr; i++) { >> + buf_hdr[i] = hdr; >> + /* odp_prefetch(hdr->addr); */ >> + hdr = hdr->pkt.next; >> + buf_hdr[i]->pkt.next = NULL; >> + } >> + >> + queue->s.head = hdr; >> + >> + if (hdr == NULL) { >> + /* Queue is now empty */ >> + queue->s.tail = NULL; >> + } >> + } >> + >> + UNLOCK(&queue->s.lock); >> + >> + return i; >> +} >> + >> + >> +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int num) >> +{ >> + queue_entry_t *queue; >> + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; >> + int i, ret; >> + >> + if (num > QUEUE_MULTI_MAX) >> + num = QUEUE_MULTI_MAX; >> + >> + queue = queue_to_qentry(handle); >> + >> + ret = queue->s.dequeue_multi(queue, buf_hdr, num); >> + >> + for (i = 0; i < ret; i++) >> + buf[i] = (odp_buffer_t) buf_hdr[i]; >> + >> + return ret; >> +} >> + >> + >> +odp_buffer_t odp_queue_deq(odp_queue_t handle) >> +{ >> + queue_entry_t *queue; >> + odp_buffer_hdr_t *buf_hdr; >> + >> + queue = queue_to_qentry(handle); >> + buf_hdr = queue->s.dequeue(queue); >> + >> + if (buf_hdr) >> + return (odp_buffer_t) buf_hdr; >> + >> + return ODP_BUFFER_INVALID; >> +} >> + >> + >> +void queue_lock(queue_entry_t *queue) >> +{ >> + LOCK(&queue->s.lock); >> +} >> + >> + >> +void queue_unlock(queue_entry_t *queue) >> +{ >> + UNLOCK(&queue->s.lock); >> +} >> -- >> 1.9.1 >> >> >> _______________________________________________ >> lng-odp mailing list >> lng-odp@lists.linaro.org >> http://lists.linaro.org/mailman/listinfo/lng-odp >> > > > > -- > *Mike Holmes* > Linaro Technical Manager / Lead > LNG - ODP >
On 12 July 2014 04:20, Venkatesh Vivekanandan < venkatesh.vivekanandan@linaro.org> wrote: > > > > On 12 July 2014 01:14, Mike Holmes <mike.holmes@linaro.org> wrote: > >> Adds whitespace errors when applied. >> > > Ran checkpatch.pl before submitting the patch. Please point to the > error/warning if any. > mike@fedora1:~/git/odp$ git am ~/incoming/lng-odp_PATCH_1-2_initial_odp_dpdk.mbox Applying: initial odp dpdk error: platform/linux-dpdk/Makefile: already exists in working directory /home/mike/git/odp/.git/rebase-apply/patch:216: new blank line at EOF. + /home/mike/git/odp/.git/rebase-apply/patch:792: new blank line at EOF. + /home/mike/git/odp/.git/rebase-apply/patch:988: new blank line at EOF. + /home/mike/git/odp/.git/rebase-apply/patch:1134: new blank line at EOF. + /home/mike/git/odp/.git/rebase-apply/patch:1192: new blank line at EOF. + Patch failed at 0001 initial odp dpdk The copy of the patch that failed is found in: /home/mike/git/odp/.git/rebase-apply/patch When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". > > >> Also needs a README like the one in linux-keystone to indicate such >> things as setting ./configure --with-platform=linux-dpdk >> And how to then ensure dpdk is installed to resolve things like >> > > Forgot to mention that prerequisite is, dpdk should be checked out and > compiled. I will probably add it in a README and send out a patch for that. > > >> /usr/include/stdc-predef.h:59:1: fatal error: >> ../../../dpdk/build/include/rte_config.h: No such file or directory >> > >> >> On 11 July 2014 14:35, <venkatesh.vivekanandan@linaro.org> wrote: >> >>> From: Vincent Hsu <vincent.hsu@linaro.org> >>> >>> Signed-off-by: Venkatesh Vivekanandan <venkatesh.vivekanandan@linaro.org >>> > >>> --- >>> platform/linux-dpdk/Makefile | 158 ++++++ >>> platform/linux-dpdk/Makefile.inc | 7 + >>> platform/linux-dpdk/include/api/odp_buffer.h | 101 ++++ >>> platform/linux-dpdk/include/api/odp_buffer_pool.h | 99 ++++ >>> platform/linux-dpdk/include/api/odp_packet.h | 228 +++++++++ >>> platform/linux-dpdk/include/api/odp_pktio_types.h | 45 ++ >>> platform/linux-dpdk/include/odp_buffer_internal.h | 79 +++ >>> .../linux-dpdk/include/odp_buffer_pool_internal.h | 90 ++++ >>> platform/linux-dpdk/include/odp_packet_dpdk.h | 88 ++++ >>> platform/linux-dpdk/include/odp_packet_internal.h | 140 +++++ >>> .../linux-dpdk/include/odp_packet_io_internal.h | 52 ++ >>> platform/linux-dpdk/source/odp_buffer.c | 102 ++++ >>> platform/linux-dpdk/source/odp_buffer_pool.c | 156 ++++++ >>> platform/linux-dpdk/source/odp_init.c | 113 +++++ >>> platform/linux-dpdk/source/odp_packet.c | 374 ++++++++++++++ >>> platform/linux-dpdk/source/odp_packet_dpdk.c | 177 +++++++ >>> platform/linux-dpdk/source/odp_packet_io.c | 561 >>> +++++++++++++++++++++ >>> platform/linux-dpdk/source/odp_queue.c | 435 >>> ++++++++++++++++ >>> 18 files changed, 3005 insertions(+) >>> create mode 100644 platform/linux-dpdk/Makefile >>> create mode 100644 platform/linux-dpdk/Makefile.inc >>> create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h >>> create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h >>> create mode 100644 platform/linux-dpdk/include/api/odp_packet.h >>> create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h >>> create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h >>> create mode 100644 >>> platform/linux-dpdk/include/odp_buffer_pool_internal.h >>> create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h >>> create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h >>> create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h >>> create mode 100644 platform/linux-dpdk/source/odp_buffer.c >>> create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c >>> create mode 100644 platform/linux-dpdk/source/odp_init.c >>> create mode 100644 platform/linux-dpdk/source/odp_packet.c >>> create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c >>> create mode 100644 platform/linux-dpdk/source/odp_packet_io.c >>> create mode 100644 platform/linux-dpdk/source/odp_queue.c >>> >>> diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile >>> new file mode 100644 >>> index 0000000..bf8d0b3 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/Makefile >>> @@ -0,0 +1,158 @@ >>> +## Copyright (c) 2013, Linaro Limited >>> +## All rights reserved. >>> +## >>> +## Redistribution and use in source and binary forms, with or without >>> +## modification, are permitted provided that the following conditions >>> are met: >>> +## >>> +## * Redistributions of source code must retain the above copyright >>> notice, this >>> +## list of conditions and the following disclaimer. >>> +## >>> +## * Redistributions in binary form must reproduce the above >>> copyright notice, this >>> +## list of conditions and the following disclaimer in the >>> documentation and/or >>> +## other materials provided with the distribution. >>> +## >>> +## * Neither the name of Linaro Limited nor the names of its >>> contributors may be >>> +## used to endorse or promote products derived from this software >>> without specific >>> +## prior written permission. >>> +## >>> +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >>> "AS IS" AND >>> +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >>> THE IMPLIED >>> +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >>> ARE >>> +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS >>> BE LIABLE >>> +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >>> CONSEQUENTIAL >>> +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE >>> GOODS OR >>> +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >>> HOWEVER >>> +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >>> LIABILITY, >>> +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT >>> OF THE USE >>> +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >>> + >>> +.DEFAULT_GOAL := libs >>> + >>> +ODP_ROOT = ../.. >>> +LIB_DIR = ./lib >>> +DOC_DIR = ./doc >>> + >>> +LINUX_GENERIC_DIR = ../linux-generic >>> + >>> +RTE_SDK ?= $(abspath $(ODP_ROOT)/../dpdk) >>> +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build) >>> +RTE_LIB ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a) >>> + >>> +PLAT_CFLAGS = -include $(RTE_OUTPUT)/include/rte_config.h >>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include >>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch >>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env >>> +PLAT_CFLAGS += -msse4.2 >>> + >>> +EXTRA_CFLAGS += $(PLAT_CFLAGS) >>> +EXTRA_CFLAGS += -I./include >>> +EXTRA_CFLAGS += -I./include/api >>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include >>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api >>> +EXTRA_CFLAGS += -I$(ODP_ROOT)/include >>> + >>> +include $(ODP_ROOT)/Makefile.inc >>> +STATIC_LIB = ./lib/libodp.a >>> + >>> +# >>> +# Object files >>> +# >>> +OBJS = >>> +OBJS += $(OBJ_DIR)/odp_barrier.o >>> +OBJS += $(OBJ_DIR)/odp_buffer.o >>> +OBJS += $(OBJ_DIR)/odp_buffer_pool.o >>> +OBJS += $(OBJ_DIR)/odp_coremask.o >>> +OBJS += $(OBJ_DIR)/odp_init.o >>> +OBJS += $(OBJ_DIR)/odp_linux.o >>> +OBJS += $(OBJ_DIR)/odp_packet.o >>> +OBJS += $(OBJ_DIR)/odp_packet_flags.o >>> +OBJS += $(OBJ_DIR)/odp_packet_io.o >>> +OBJS += $(OBJ_DIR)/odp_packet_socket.o >>> +OBJS += $(OBJ_DIR)/odp_queue.o >>> +OBJS += $(OBJ_DIR)/odp_schedule.o >>> +OBJS += $(OBJ_DIR)/odp_shared_memory.o >>> +OBJS += $(OBJ_DIR)/odp_spinlock.o >>> +OBJS += $(OBJ_DIR)/odp_system_info.o >>> +OBJS += $(OBJ_DIR)/odp_thread.o >>> +OBJS += $(OBJ_DIR)/odp_ticketlock.o >>> +OBJS += $(OBJ_DIR)/odp_time.o >>> +OBJS += $(OBJ_DIR)/odp_timer.o >>> +OBJS += $(OBJ_DIR)/odp_ring.o >>> +OBJS += $(OBJ_DIR)/odp_rwlock.o >>> +OBJS += $(OBJ_DIR)/odp_packet_dpdk.o >>> + >>> +DEPS = $(OBJS:.o=.d) >>> + >>> +.PHONY: all >>> +all: libs docs >>> + >>> +-include $(DEPS) >>> + >>> +#$(OBJ_DIR): >>> +# $(MKDIR) $(OBJ_DIR) >>> + >>> +$(LIB_DIR): >>> + $(MKDIR) $(LIB_DIR) >>> + >>> +$(DOC_DIR): >>> + $(MKDIR) $(DOC_DIR)/html >>> + $(MKDIR) $(DOC_DIR)/latex >>> + >>> +# >>> +# Compile rules >>> +# >>> +vpath %.c source:$(LINUX_GENERIC_DIR)/source >>> + >>> +$(OBJ_DIR)/%.o: %.c >>> + $(ECHO) " CC $<" >>> + $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $< >>> + >>> +# >>> +# Lib rule >>> +# >>> +$(OBJ_DIR)/libodp.o: $(OBJS) >>> + $(ECHO) " LD $@" >>> + $(LD) -r -o $@ $(OBJS) $(RTE_LIB) >>> + >>> +$(STATIC_LIB): $(OBJ_DIR)/libodp.o >>> + $(ECHO) " AR $@" >>> + $(AR) -cr $@ $(OBJ_DIR)/libodp.o >>> + >>> + >>> +clean: >>> + $(RMDIR) $(OBJ_DIR) >>> + $(RMDIR) $(LIB_DIR) >>> + $(RMDIR) $(DOC_DIR) >>> + $(RM) Doxyfile >>> + >>> +Doxyfile: Doxyfile.in >>> + doxygen -u - < $< > $@ >>> + >>> +.PHONY: docs >>> +docs: $(DOC_DIR) Doxyfile ./include/odp*.h >>> + doxygen >>> + >>> +.PHONY: docs_install >>> +docs_install: docs >>> + $(COPY) doc $(DESTDIR) >>> + >>> +.PHONY: pdf >>> +pdf: docs >>> + make --directory doc/latex refman.pdf 1> /dev/null >>> + >>> +.PHONY: libs >>> +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB) >>> + >>> +.PHONY: lib_install >>> +lib_install: libs >>> + install -d $(DESTDIR)/lib >>> + install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/ >>> + >>> +.PHONY: headers_install >>> +headers_install: libs >>> + $(ECHO) Installing headers to $(DESTDIR)/include >>> + $(COPY) $(ODP_ROOT)/include $(DESTDIR) >>> + $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/ >>> + $(COPY) include/api/* $(DESTDIR)/include/ >>> + >>> +install: lib_install headers_install >>> diff --git a/platform/linux-dpdk/Makefile.inc >>> b/platform/linux-dpdk/Makefile.inc >>> new file mode 100644 >>> index 0000000..fe7679b >>> --- /dev/null >>> +++ b/platform/linux-dpdk/Makefile.inc >>> @@ -0,0 +1,7 @@ >>> +# Copyright (c) 2013, Linaro Limited >>> +# All rights reserved. >>> +# >>> +# SPDX-License-Identifier: BSD-3-Clause >>> + >>> +STD_LIBS += -ldl >>> + >>> diff --git a/platform/linux-dpdk/include/api/odp_buffer.h >>> b/platform/linux-dpdk/include/api/odp_buffer.h >>> new file mode 100644 >>> index 0000000..286d9e6 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/api/odp_buffer.h >>> @@ -0,0 +1,101 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> + >>> +/** >>> + * @file >>> + * >>> + * ODP buffer descriptor >>> + */ >>> + >>> +#ifndef ODP_BUFFER_H_ >>> +#define ODP_BUFFER_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> + >>> + >>> +#include <odp_std_types.h> >>> + >>> + >>> + >>> + >>> + >>> +/** >>> + * ODP buffer >>> + */ >>> +typedef unsigned long odp_buffer_t; >>> + >>> + >>> +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */ >>> + >>> + >>> +/** >>> + * Buffer start address >>> + * >>> + * @param buf Buffer handle >>> + * >>> + * @return Buffer start address >>> + */ >>> +void *odp_buffer_addr(odp_buffer_t buf); >>> + >>> +/** >>> + * Buffer maximum data size >>> + * >>> + * @param buf Buffer handle >>> + * >>> + * @return Buffer maximum data size >>> + */ >>> +size_t odp_buffer_size(odp_buffer_t buf); >>> + >>> +/** >>> + * Buffer type >>> + * >>> + * @param buf Buffer handle >>> + * >>> + * @return Buffer type >>> + */ >>> +int odp_buffer_type(odp_buffer_t buf); >>> + >>> +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */ >>> +#define ODP_BUFFER_TYPE_RAW 0 /**< Raw buffer */ >>> +#define ODP_BUFFER_TYPE_PACKET 1 /**< Packet buffer */ >>> +#define ODP_BUFFER_TYPE_TIMER 2 /**< Timer buffer */ >>> + >>> +/** >>> + * Tests if buffer is part of a scatter/gather list >>> + * >>> + * @param buf Buffer handle >>> + * >>> + * @return 1 if belongs to a scatter list, otherwise 0 >>> + */ >>> +int odp_buffer_is_scatter(odp_buffer_t buf); >>> + >>> +/** >>> + * Tests if buffer is valid >>> + * >>> + * @param buf Buffer handle >>> + * >>> + * @return 1 if valid, otherwise 0 >>> + */ >>> +int odp_buffer_is_valid(odp_buffer_t buf); >>> + >>> +/** >>> + * Print buffer metadata to STDOUT >>> + * >>> + * @param buf Buffer handle >>> + * >>> + */ >>> +void odp_buffer_print(odp_buffer_t buf); >>> + >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h >>> b/platform/linux-dpdk/include/api/odp_buffer_pool.h >>> new file mode 100644 >>> index 0000000..4b75cf5 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h >>> @@ -0,0 +1,99 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> + >>> +/** >>> + * @file >>> + * >>> + * ODP buffer pool >>> + */ >>> + >>> +#ifndef ODP_BUFFER_POOL_H_ >>> +#define ODP_BUFFER_POOL_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> + >>> + >>> +#include <odp_std_types.h> >>> +#include <odp_buffer.h> >>> + >>> +/** Maximum queue name lenght in chars */ >>> +#define ODP_BUFFER_POOL_NAME_LEN 32 >>> + >>> +/** Invalid buffer pool */ >>> +#define ODP_BUFFER_POOL_INVALID (0xffffffff) >>> + >>> +/** ODP buffer pool */ >>> +typedef unsigned long odp_buffer_pool_t; >>> + >>> + >>> +/** >>> + * Create a buffer pool >>> + * >>> + * @param name Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1 >>> chars) >>> + * @param base_addr Pool base address >>> + * @param size Pool size in bytes >>> + * @param buf_size Buffer size in bytes >>> + * @param buf_align Minimum buffer alignment >>> + * @param buf_type Buffer type >>> + * >>> + * @return Buffer pool handle >>> + */ >>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name, >>> + void *base_addr, uint64_t size, >>> + size_t buf_size, size_t >>> buf_align, >>> + int buf_type); >>> + >>> + >>> +/** >>> + * Find a buffer pool by name >>> + * >>> + * @param name Name of the pool >>> + * >>> + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found. >>> + */ >>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name); >>> + >>> + >>> +/** >>> + * Print buffer pool info >>> + * >>> + * @param pool Pool handle >>> + * >>> + */ >>> +void odp_buffer_pool_print(odp_buffer_pool_t pool); >>> + >>> + >>> + >>> +/** >>> + * Buffer alloc >>> + * >>> + * @param pool Pool handle >>> + * >>> + * @return Buffer handle or ODP_BUFFER_INVALID >>> + */ >>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool); >>> + >>> + >>> +/** >>> + * Buffer free >>> + * >>> + * @param buf Buffer handle >>> + * >>> + */ >>> +void odp_buffer_free(odp_buffer_t buf); >>> + >>> + >>> + >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/platform/linux-dpdk/include/api/odp_packet.h >>> b/platform/linux-dpdk/include/api/odp_packet.h >>> new file mode 100644 >>> index 0000000..bdb3417 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/api/odp_packet.h >>> @@ -0,0 +1,228 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> + >>> +/** >>> + * @file >>> + * >>> + * ODP packet descriptor >>> + */ >>> + >>> +#ifndef ODP_PACKET_H_ >>> +#define ODP_PACKET_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp_buffer.h> >>> + >>> + >>> +/** >>> + * ODP packet descriptor >>> + */ >>> +typedef unsigned long odp_packet_t; >>> + >>> + >>> +/** Invalid packet */ >>> +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID >>> + >>> +/** Invalid offset */ >>> +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1) >>> + >>> + >>> +/** >>> + * Initialize the packet >>> + * >>> + * Needs to be called if the user allocates a packet buffer, i.e. the >>> packet >>> + * has not been received from I/O through ODP. >>> + * >>> + * @param pkt Packet handle >>> + */ >>> +void odp_packet_init(odp_packet_t pkt); >>> + >>> +/** >>> + * Convert from packet handle to buffer handle >>> + * >>> + * @param buf Buffer handle >>> + * >>> + * @return Packet handle >>> + */ >>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf); >>> + >>> +/** >>> + * Convert from buffer handle to packet handle >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return Buffer handle >>> + */ >>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt); >>> + >>> +/** >>> + * Set the packet length >>> + * >>> + * @param pkt Packet handle >>> + * @param len Length of packet in bytes >>> + */ >>> +void odp_packet_set_len(odp_packet_t pkt, size_t len); >>> + >>> +/** >>> + * Get the packet length >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return Packet length in bytes >>> + */ >>> +size_t odp_packet_get_len(odp_packet_t pkt); >>> + >>> +/** >>> + * Get address to the start of the packet buffer >>> + * >>> + * The address of the packet buffer is not necessarily the same as the >>> start >>> + * address of the received frame, e.g. an eth frame may be offset by 2 >>> or 6 >>> + * bytes to ensure 32 or 64-bit alignment of the IP header. >>> + * Use odp_packet_l2(pkt) to get the start address of a received valid >>> frame >>> + * or odp_packet_start(pkt) to get the start address even if no valid >>> L2 header >>> + * could be found. >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return Pointer to the start of the packet buffer >>> + * >>> + * @see odp_packet_l2(), odp_packet_start() >>> + */ >>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt); >>> + >>> +/** >>> + * Get pointer to the start of the received frame >>> + * >>> + * The address of the packet buffer is not necessarily the same as the >>> start >>> + * address of the received frame, e.g. an eth frame may be offset by 2 >>> or 6 >>> + * bytes to ensure 32 or 64-bit alignment of the IP header. >>> + * Use odp_packet_l2(pkt) to get the start address of a received valid >>> eth frame >>> + * >>> + * odp_packet_start() will always return a pointer to the start of the >>> frame, >>> + * even if the frame is unrecognized and no valid L2 header could be >>> found. >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return Pointer to the start of the received frame >>> + * >>> + * @see odp_packet_l2(), odp_packet_buf_addr() >>> + */ >>> +uint8_t *odp_packet_start(odp_packet_t pkt); >>> + >>> +/** >>> + * Get pointer to the start of the L2 frame >>> + * >>> + * The L2 frame header address is not necessarily the same as the >>> address of the >>> + * packet buffer, see odp_packet_buf_addr() >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return Pointer to L2 header or NULL if not found >>> + * >>> + * @see odp_packet_buf_addr(), odp_packet_start() >>> + */ >>> +uint8_t *odp_packet_l2(odp_packet_t pkt); >>> + >>> +/** >>> + * Return the byte offset from the packet buffer to the L2 frame >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found >>> + */ >>> +size_t odp_packet_l2_offset(odp_packet_t pkt); >>> + >>> +/** >>> + * Set the byte offset to the L2 frame >>> + * >>> + * @param pkt Packet handle >>> + * @param offset L2 byte offset >>> + */ >>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset); >>> + >>> + >>> +/** >>> + * Get pointer to the start of the L3 packet >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return Pointer to L3 packet or NULL if not found >>> + * >>> + */ >>> +uint8_t *odp_packet_l3(odp_packet_t pkt); >>> + >>> +/** >>> + * Return the byte offset from the packet buffer to the L3 packet >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found >>> + */ >>> +size_t odp_packet_l3_offset(odp_packet_t pkt); >>> + >>> +/** >>> + * Set the byte offset to the L3 packet >>> + * >>> + * @param pkt Packet handle >>> + * @param offset L3 byte offset >>> + */ >>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset); >>> + >>> + >>> +/** >>> + * Get pointer to the start of the L4 packet >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return Pointer to L4 packet or NULL if not found >>> + * >>> + */ >>> +uint8_t *odp_packet_l4(odp_packet_t pkt); >>> + >>> +/** >>> + * Return the byte offset from the packet buffer to the L4 packet >>> + * >>> + * @param pkt Packet handle >>> + * >>> + * @return L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found >>> + */ >>> +size_t odp_packet_l4_offset(odp_packet_t pkt); >>> + >>> +/** >>> + * Set the byte offset to the L4 packet >>> + * >>> + * @param pkt Packet handle >>> + * @param offset L4 byte offset >>> + */ >>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset); >>> + >>> +/** >>> + * Print (debug) information about the packet >>> + * >>> + * @param pkt Packet handle >>> + */ >>> +void odp_packet_print(odp_packet_t pkt); >>> + >>> +/** >>> + * Copy contents and metadata from pkt_src to pkt_dst >>> + * Useful when creating copies of packets >>> + * >>> + * @param pkt_dst Destination packet >>> + * @param pkt_src Source packet >>> + * >>> + * @return 0 if successful >>> + */ >>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src); >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h >>> b/platform/linux-dpdk/include/api/odp_pktio_types.h >>> new file mode 100644 >>> index 0000000..b23e6da >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h >>> @@ -0,0 +1,45 @@ >>> + >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#ifndef ODP_PKTIO_TYPES_H >>> +#define ODP_PKTIO_TYPES_H >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +/* We should ensure that future enum values will never overlap, >>> otherwise >>> + * applications that want netmap suport might get in trouble if the odp >>> lib >>> + * was not built with netmap support and there are more types define >>> below >>> + */ >>> + >>> +typedef enum { >>> + ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1, >>> + ODP_PKTIO_TYPE_SOCKET_MMSG, >>> + ODP_PKTIO_TYPE_SOCKET_MMAP, >>> + ODP_PKTIO_TYPE_NETMAP, >>> + ODP_PKTIO_TYPE_DPDK, >>> +} odp_pktio_type_t; >>> + >>> +#include <odp_pktio_socket.h> >>> +#ifdef ODP_HAVE_NETMAP >>> +#include <odp_pktio_netmap.h> >>> +#endif >>> + >>> +typedef union odp_pktio_params_t { >>> + odp_pktio_type_t type; >>> + socket_params_t sock_params; >>> +#ifdef ODP_HAVE_NETMAP >>> + netmap_params_t nm_params; >>> +#endif >>> +} odp_pktio_params_t; >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h >>> b/platform/linux-dpdk/include/odp_buffer_internal.h >>> new file mode 100644 >>> index 0000000..a47107c >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/odp_buffer_internal.h >>> @@ -0,0 +1,79 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> + >>> +/** >>> + * @file >>> + * >>> + * ODP buffer descriptor - implementation internal >>> + */ >>> + >>> +#ifndef ODP_BUFFER_INTERNAL_H_ >>> +#define ODP_BUFFER_INTERNAL_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp_std_types.h> >>> +#include <odp_atomic.h> >>> +#include <odp_buffer_pool.h> >>> +#include <odp_buffer.h> >>> +#include <odp_debug.h> >>> +#include <odp_align.h> >>> +#include <rte_mbuf.h> >>> + >>> +/* TODO: move these to correct files */ >>> + >>> +typedef uint64_t odp_phys_addr_t; >>> + >>> +#define ODP_BUFFER_MAX_INDEX (ODP_BUFFER_MAX_BUFFERS - 2) >>> +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1) >>> + >>> +#define ODP_BUFS_PER_CHUNK 16 >>> +#define ODP_BUFS_PER_SCATTER 4 >>> + >>> +#define ODP_BUFFER_TYPE_CHUNK 0xffff >>> + >>> + >>> +#define ODP_BUFFER_POOL_BITS 4 >>> +#define ODP_BUFFER_INDEX_BITS (32 - ODP_BUFFER_POOL_BITS) >>> +#define ODP_BUFFER_MAX_POOLS (1 << ODP_BUFFER_POOL_BITS) >>> +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS) >>> + >>> +typedef union odp_buffer_bits_t { >>> + uint32_t u32; >>> + odp_buffer_t handle; >>> + >>> + struct { >>> + uint32_t pool:ODP_BUFFER_POOL_BITS; >>> + uint32_t index:ODP_BUFFER_INDEX_BITS; >>> + }; >>> +} odp_buffer_bits_t; >>> + >>> + >>> +/* forward declaration */ >>> +struct odp_buffer_hdr_t; >>> + >>> + >>> +typedef struct rte_mbuf odp_buffer_hdr_t; >>> + >>> + >>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf); >>> + >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> + >>> + >>> + >>> + >>> + >>> + >>> + >>> diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h >>> b/platform/linux-dpdk/include/odp_buffer_pool_internal.h >>> new file mode 100644 >>> index 0000000..1a36655 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h >>> @@ -0,0 +1,90 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> + >>> +/** >>> + * @file >>> + * >>> + * ODP buffer pool - internal header >>> + */ >>> + >>> +#ifndef ODP_BUFFER_POOL_INTERNAL_H_ >>> +#define ODP_BUFFER_POOL_INTERNAL_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp_std_types.h> >>> +#include <odp_buffer_pool.h> >>> +#include <odp_buffer_internal.h> >>> +#include <odp_align.h> >>> +#include <odp_hints.h> >>> +#include <odp_config.h> >>> +#include <odp_debug.h> >>> + >>> +/* for DPDK */ >>> +#include <rte_mempool.h> >>> + >>> +/* Use ticketlock instead of spinlock */ >>> +#define POOL_USE_TICKETLOCK >>> + >>> +/* Extra error checks */ >>> +/* #define POOL_ERROR_CHECK */ >>> + >>> + >>> +#ifdef POOL_USE_TICKETLOCK >>> +#include <odp_ticketlock.h> >>> +#else >>> +#include <odp_spinlock.h> >>> +#endif >>> + >>> + >>> +struct pool_entry_s { >>> +#ifdef POOL_USE_TICKETLOCK >>> + odp_ticketlock_t lock ODP_ALIGNED_CACHE; >>> +#else >>> + odp_spinlock_t lock ODP_ALIGNED_CACHE; >>> +#endif >>> + >>> + uint64_t free_bufs; >>> + char name[ODP_BUFFER_POOL_NAME_LEN]; >>> + >>> + >>> + odp_buffer_pool_t pool ODP_ALIGNED_CACHE; >>> + uintptr_t buf_base; >>> + size_t buf_size; >>> + size_t buf_offset; >>> + uint64_t num_bufs; >>> + void *pool_base_addr; >>> + uint64_t pool_size; >>> + size_t payload_size; >>> + size_t payload_align; >>> + int buf_type; >>> + size_t hdr_size; >>> +}; >>> + >>> + >>> +extern void *pool_entry_ptr[]; >>> + >>> + >>> +static inline void *get_pool_entry(odp_buffer_pool_t pool_id) >>> +{ >>> + return pool_entry_ptr[pool_id]; >>> +} >>> + >>> + >>> +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf) >>> +{ >>> + return (odp_buffer_hdr_t *)buf; >>> +} >>> + >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h >>> b/platform/linux-dpdk/include/odp_packet_dpdk.h >>> new file mode 100644 >>> index 0000000..0b3db08 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h >>> @@ -0,0 +1,88 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#ifndef ODP_PACKET_DPDK_H >>> +#define ODP_PACKET_DPDK_H >>> + >>> +#include <stdint.h> >>> +#include <net/if.h> >>> + >>> +#include <helper/odp_eth.h> >>> +#include <helper/odp_packet_helper.h> >>> +#include <odp_align.h> >>> +#include <odp_debug.h> >>> +#include <odp_packet.h> >>> +#include <odp_packet_internal.h> >>> +#include <odp_buffer_pool.h> >>> +#include <odp_buffer_pool_internal.h> >>> +#include <odp_buffer_internal.h> >>> +#include <odp_std_types.h> >>> + >>> +#include <rte_config.h> >>> +#include <rte_memory.h> >>> +#include <rte_memzone.h> >>> +#include <rte_launch.h> >>> +#include <rte_tailq.h> >>> +#include <rte_eal.h> >>> +#include <rte_per_lcore.h> >>> +#include <rte_lcore.h> >>> +#include <rte_branch_prediction.h> >>> +#include <rte_prefetch.h> >>> +#include <rte_cycles.h> >>> +#include <rte_errno.h> >>> +#include <rte_debug.h> >>> +#include <rte_log.h> >>> +#include <rte_byteorder.h> >>> +#include <rte_pci.h> >>> +#include <rte_random.h> >>> +#include <rte_ether.h> >>> +#include <rte_ethdev.h> >>> +#include <rte_hash.h> >>> +#include <rte_jhash.h> >>> +#include <rte_hash_crc.h> >>> + >>> + >>> +#define ODP_DPDK_MODE_HW 0 >>> +#define ODP_DPDK_MODE_SW 1 >>> + >>> +#define DPDK_BLOCKING_IO >>> + >>> +/** Packet socket using dpdk mmaped rings for both Rx and Tx */ >>> +typedef struct { >>> + odp_buffer_pool_t pool; >>> + >>> + /********************************/ >>> + char ifname[32]; >>> + uint8_t portid; >>> + uint16_t queueid; >>> +} pkt_dpdk_t; >>> + >>> +/** >>> + * Configure an interface to work in dpdk mode >>> + */ >>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, >>> + odp_buffer_pool_t pool); >>> + >>> +/** >>> + * Switch interface from dpdk mode to normal mode >>> + */ >>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk); >>> + >>> +/** >>> + * Receive packets using dpdk >>> + */ >>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], >>> + unsigned len); >>> + >>> +/** >>> + * Send packets using dpdk >>> + */ >>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], >>> + unsigned len); >>> + >>> +int odp_init_dpdk(void); >>> +#endif >>> + >>> diff --git a/platform/linux-dpdk/include/odp_packet_internal.h >>> b/platform/linux-dpdk/include/odp_packet_internal.h >>> new file mode 100644 >>> index 0000000..d9057a2 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/odp_packet_internal.h >>> @@ -0,0 +1,140 @@ >>> +/* Copyright (c) 2014, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> + >>> +/** >>> + * @file >>> + * >>> + * ODP packet descriptor - implementation internal >>> + */ >>> + >>> +#ifndef ODP_PACKET_INTERNAL_H_ >>> +#define ODP_PACKET_INTERNAL_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp_align.h> >>> +#include <odp_debug.h> >>> +#include <odp_buffer_internal.h> >>> +#include <odp_buffer_pool_internal.h> >>> +#include <odp_packet.h> >>> +#include <odp_packet_io.h> >>> + >>> +/** >>> + * Packet input & protocol flags >>> + */ >>> +typedef union { >>> + /* All input flags */ >>> + uint32_t all; >>> + >>> + struct { >>> + /* Bitfield flags for each protocol */ >>> + uint32_t l2:1; /**< known L2 protocol present */ >>> + uint32_t l3:1; /**< known L3 protocol present */ >>> + uint32_t l4:1; /**< known L4 protocol present */ >>> + >>> + uint32_t eth:1; /**< Ethernet */ >>> + uint32_t jumbo:1; /**< Jumbo frame */ >>> + uint32_t vlan:1; /**< VLAN hdr found */ >>> + uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */ >>> + >>> + uint32_t arp:1; /**< ARP */ >>> + >>> + uint32_t ipv4:1; /**< IPv4 */ >>> + uint32_t ipv6:1; /**< IPv6 */ >>> + uint32_t ipfrag:1; /**< IP fragment */ >>> + uint32_t ipopt:1; /**< IP optional headers */ >>> + uint32_t ipsec:1; /**< IPSec decryption may be >>> needed */ >>> + >>> + uint32_t udp:1; /**< UDP */ >>> + uint32_t tcp:1; /**< TCP */ >>> + uint32_t sctp:1; /**< SCTP */ >>> + uint32_t icmp:1; /**< ICMP */ >>> + }; >>> +} input_flags_t; >>> + >>> +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t), >>> INPUT_FLAGS_SIZE_ERROR); >>> + >>> +/** >>> + * Packet error flags >>> + */ >>> +typedef union { >>> + /* All error flags */ >>> + uint32_t all; >>> + >>> + struct { >>> + /* Bitfield flags for each detected error */ >>> + uint32_t frame_len:1; /**< Frame length error */ >>> + uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD >>> */ >>> + uint32_t ip_err:1; /**< IP error, checks TBD */ >>> + uint32_t tcp_err:1; /**< TCP error, checks TBD */ >>> + uint32_t udp_err:1; /**< UDP error, checks TBD */ >>> + }; >>> +} error_flags_t; >>> + >>> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t), >>> ERROR_FLAGS_SIZE_ERROR); >>> + >>> +/** >>> + * Packet output flags >>> + */ >>> +typedef union { >>> + /* All output flags */ >>> + uint32_t all; >>> + >>> + struct { >>> + /* Bitfield flags for each output option */ >>> + uint32_t l4_chksum:1; /**< Request L4 checksum >>> calculation */ >>> + }; >>> +} output_flags_t; >>> + >>> +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), >>> OUTPUT_FLAGS_SIZE_ERROR); >>> + >>> +/** >>> + * Internal Packet header >>> + */ >>> +typedef struct { >>> + /* common buffer header */ >>> + odp_buffer_hdr_t buf_hdr; >>> + >>> + input_flags_t input_flags; >>> + error_flags_t error_flags; >>> + output_flags_t output_flags; >>> + >>> + uint32_t frame_offset; /**< offset to start of frame, even on >>> error */ >>> + uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */ >>> + uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */ >>> + uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also >>> ICMP) */ >>> + >>> + uint32_t frame_len; >>> + >>> + odp_pktio_t input; >>> + >>> + uint32_t pad; >>> + uint8_t payload[]; >>> + >>> +} odp_packet_hdr_t; >>> + >>> +/** >>> + * Return the packet header >>> + */ >>> +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt) >>> +{ >>> + return (odp_packet_hdr_t *)pkt; >>> +} >>> + >>> +/** >>> + * Parse packet and set internal metadata >>> + */ >>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset); >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> + >>> diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h >>> b/platform/linux-dpdk/include/odp_packet_io_internal.h >>> new file mode 100644 >>> index 0000000..5948063 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h >>> @@ -0,0 +1,52 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> + >>> +/** >>> + * @file >>> + * >>> + * ODP packet IO - implementation internal >>> + */ >>> + >>> +#ifndef ODP_PACKET_IO_INTERNAL_H_ >>> +#define ODP_PACKET_IO_INTERNAL_H_ >>> + >>> +#ifdef __cplusplus >>> +extern "C" { >>> +#endif >>> + >>> +#include <odp_spinlock.h> >>> +#include <odp_packet_socket.h> >>> +#ifdef ODP_HAVE_NETMAP >>> +#include <odp_packet_netmap.h> >>> +#endif >>> +#include <odp_packet_dpdk.h> >>> + >>> +struct pktio_entry { >>> + odp_spinlock_t lock; /**< entry spinlock */ >>> + int taken; /**< is entry taken(1) or >>> free(0) */ >>> + odp_queue_t inq_default; /**< default input queue, if set >>> */ >>> + odp_queue_t outq_default; /**< default out queue */ >>> + odp_pktio_params_t params; /**< pktio parameters */ >>> + pkt_sock_t pkt_sock; /**< using socket API for IO */ >>> + pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap API for >>> IO */ >>> +#ifdef ODP_HAVE_NETMAP >>> + pkt_netmap_t pkt_nm; /**< using netmap API for IO */ >>> +#endif >>> + pkt_dpdk_t pkt_dpdk; /**< using DPDK API for IO */ >>> +}; >>> + >>> +typedef union { >>> + struct pktio_entry s; >>> + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct >>> pktio_entry))]; >>> +} pktio_entry_t; >>> + >>> +#ifdef __cplusplus >>> +} >>> +#endif >>> + >>> +#endif >>> + >>> diff --git a/platform/linux-dpdk/source/odp_buffer.c >>> b/platform/linux-dpdk/source/odp_buffer.c >>> new file mode 100644 >>> index 0000000..bfb5ff6 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/source/odp_buffer.c >>> @@ -0,0 +1,102 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#include <odp_buffer.h> >>> +#include <odp_buffer_internal.h> >>> +#include <odp_buffer_pool_internal.h> >>> + >>> +#include <string.h> >>> +#include <stdio.h> >>> + >>> + >>> +void *odp_buffer_addr(odp_buffer_t buf) >>> +{ >>> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >>> + >>> + return hdr->buf_addr; >>> +} >>> + >>> + >>> +size_t odp_buffer_size(odp_buffer_t buf) >>> +{ >>> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >>> + >>> + return hdr->buf_len; >>> +} >>> + >>> + >>> +int odp_buffer_type(odp_buffer_t buf) >>> +{ >>> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >>> + >>> + return hdr->type; >>> +} >>> + >>> + >>> +int odp_buffer_is_scatter(odp_buffer_t buf) >>> +{ >>> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >>> + >>> + if (hdr->refcnt == 0) >>> + return 0; >>> + else >>> + return 1; >>> +} >>> + >>> + >>> +int odp_buffer_is_valid(odp_buffer_t buf) >>> +{ >>> + odp_buffer_bits_t handle; >>> + >>> + handle.u32 = buf; >>> + >>> + return (handle.index != ODP_BUFFER_INVALID_INDEX); >>> +} >>> + >>> + >>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf) >>> +{ >>> + odp_buffer_hdr_t *hdr; >>> + int len = 0; >>> + >>> + if (!odp_buffer_is_valid(buf)) { >>> + printf("Buffer is not valid.\n"); >>> + return len; >>> + } >>> + >>> + hdr = odp_buf_to_hdr(buf); >>> + >>> + len += snprintf(&str[len], n-len, >>> + "Buffer\n"); >>> + len += snprintf(&str[len], n-len, >>> + " pool %"PRIu64"\n", (int64_t) >>> hdr->pool); >>> + len += snprintf(&str[len], n-len, >>> + " phy_addr %"PRIu64"\n", hdr->buf_physaddr); >>> + len += snprintf(&str[len], n-len, >>> + " addr %p\n", hdr->buf_addr); >>> + len += snprintf(&str[len], n-len, >>> + " size %u\n", hdr->buf_len); >>> + len += snprintf(&str[len], n-len, >>> + " ref_count %i\n", hdr->refcnt); >>> + len += snprintf(&str[len], n-len, >>> + " type %i\n", hdr->type); >>> + >>> + return len; >>> +} >>> + >>> + >>> +void odp_buffer_print(odp_buffer_t buf) >>> +{ >>> + int max_len = 512; >>> + char str[max_len]; >>> + int len; >>> + >>> + len = odp_buffer_snprint(str, max_len-1, buf); >>> + str[len] = 0; >>> + >>> + printf("\n%s\n", str); >>> +} >>> + >>> diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c >>> b/platform/linux-dpdk/source/odp_buffer_pool.c >>> new file mode 100644 >>> index 0000000..de90275 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/source/odp_buffer_pool.c >>> @@ -0,0 +1,156 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#include <odp_std_types.h> >>> +#include <odp_buffer_pool.h> >>> +#include <odp_buffer_pool_internal.h> >>> +#include <odp_buffer_internal.h> >>> +#include <odp_packet_internal.h> >>> +#include <odp_shared_memory.h> >>> +#include <odp_align.h> >>> +#include <odp_internal.h> >>> +#include <odp_config.h> >>> +#include <odp_hints.h> >>> +#include <odp_debug.h> >>> + >>> +#include <string.h> >>> +#include <stdlib.h> >>> + >>> +/* for DPDK */ >>> +#include <odp_packet_dpdk.h> >>> + >>> +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + >>> RTE_PKTMBUF_HEADROOM) >>> +#define NB_MBUF 8192 >>> + >>> +#ifdef POOL_USE_TICKETLOCK >>> +#include <odp_ticketlock.h> >>> +#define LOCK(a) odp_ticketlock_lock(a) >>> +#define UNLOCK(a) odp_ticketlock_unlock(a) >>> +#define LOCK_INIT(a) odp_ticketlock_init(a) >>> +#else >>> +#include <odp_spinlock.h> >>> +#define LOCK(a) odp_spinlock_lock(a) >>> +#define UNLOCK(a) odp_spinlock_unlock(a) >>> +#define LOCK_INIT(a) odp_spinlock_init(a) >>> +#endif >>> + >>> + >>> +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS >>> +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS >>> +#endif >>> + >>> +#define NULL_INDEX ((uint32_t)-1) >>> + >>> + >>> +typedef union pool_entry_u { >>> + struct pool_entry_s s; >>> + >>> + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct >>> pool_entry_s))]; >>> + >>> +} pool_entry_t; >>> + >>> + >>> +typedef struct pool_table_t { >>> + pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS]; >>> + >>> +} pool_table_t; >>> + >>> + >>> +/* The pool table */ >>> +static pool_table_t *pool_tbl; >>> + >>> +/* Pool entry pointers (for inlining) */ >>> +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS]; >>> + >>> + >>> +int odp_buffer_pool_init_global(void) >>> +{ >>> + odp_buffer_pool_t i; >>> + >>> + pool_tbl = odp_shm_reserve("odp_buffer_pools", >>> + sizeof(pool_table_t), >>> + sizeof(pool_entry_t)); >>> + >>> + if (pool_tbl == NULL) >>> + return -1; >>> + >>> + memset(pool_tbl, 0, sizeof(pool_table_t)); >>> + >>> + >>> + for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) { >>> + /* init locks */ >>> + pool_entry_t *pool = &pool_tbl->pool[i]; >>> + LOCK_INIT(&pool->s.lock); >>> + pool->s.pool = i; >>> + >>> + pool_entry_ptr[i] = pool; >>> + } >>> + >>> + ODP_DBG("\nBuffer pool init global\n"); >>> + ODP_DBG(" pool_entry_s size %zu\n", sizeof(struct >>> pool_entry_s)); >>> + ODP_DBG(" pool_entry_t size %zu\n", sizeof(pool_entry_t)); >>> + ODP_DBG(" odp_buffer_hdr_t size %zu\n", >>> sizeof(odp_buffer_hdr_t)); >>> + ODP_DBG("\n"); >>> + >>> + return 0; >>> +} >>> + >>> + >>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name, >>> + void *base_addr, uint64_t size, >>> + size_t buf_size, size_t >>> buf_align, >>> + int buf_type) >>> +{ >>> + struct rte_mempool *pktmbuf_pool = NULL; >>> + ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n", >>> name, >>> + (uint64_t) base_addr, (unsigned) size, >>> + (unsigned) buf_size, (unsigned) buf_align, >>> + buf_type); >>> + >>> + pktmbuf_pool = >>> + rte_mempool_create(name, NB_MBUF, >>> + MBUF_SIZE, 32, >>> + sizeof(struct >>> rte_pktmbuf_pool_private), >>> + rte_pktmbuf_pool_init, NULL, >>> + rte_pktmbuf_init, NULL, >>> + rte_socket_id(), 0); >>> + if (pktmbuf_pool == NULL) { >>> + ODP_ERR("Cannot init DPDK mbuf pool\n"); >>> + return -1; >>> + } >>> + >>> + return (odp_buffer_pool_t) pktmbuf_pool; >>> +} >>> + >>> + >>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name) >>> +{ >>> + struct rte_mempool *mp = NULL; >>> + >>> + mp = rte_mempool_lookup(name); >>> + if (mp == NULL) >>> + return ODP_BUFFER_POOL_INVALID; >>> + >>> + return (odp_buffer_pool_t)mp; >>> +} >>> + >>> + >>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id) >>> +{ >>> + return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool >>> *)pool_id); >>> +} >>> + >>> + >>> +void odp_buffer_free(odp_buffer_t buf) >>> +{ >>> + rte_pktmbuf_free((struct rte_mbuf *)buf); >>> +} >>> + >>> + >>> +void odp_buffer_pool_print(odp_buffer_pool_t pool_id) >>> +{ >>> + rte_mempool_dump((const struct rte_mempool *)pool_id); >>> +} >>> diff --git a/platform/linux-dpdk/source/odp_init.c >>> b/platform/linux-dpdk/source/odp_init.c >>> new file mode 100644 >>> index 0000000..ecc2066 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/source/odp_init.c >>> @@ -0,0 +1,113 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#include <odp_init.h> >>> +#include <odp_internal.h> >>> +#include <odp_debug.h> >>> +#include <odp_packet_dpdk.h> >>> + >>> +int odp_init_dpdk(void) >>> +{ >>> + int test_argc = 5; >>> + char *test_argv[6]; >>> + int core_count, i, num_cores = 0; >>> + char core_mask[8]; >>> + >>> + core_count = odp_sys_core_count(); >>> + for (i = 0; i < core_count; i++) >>> + num_cores += (0x1 << i); >>> + sprintf(core_mask, "%x", num_cores); >>> + >>> + test_argv[0] = malloc(sizeof("odp_dpdk")); >>> + strcpy(test_argv[0], "odp_dpdk"); >>> + test_argv[1] = malloc(sizeof("-c")); >>> + strcpy(test_argv[1], "-c"); >>> + test_argv[2] = malloc(sizeof(core_mask)); >>> + strcpy(test_argv[2], core_mask); >>> + test_argv[3] = malloc(sizeof("-n")); >>> + strcpy(test_argv[3], "-n"); >>> + test_argv[4] = malloc(sizeof("3")); >>> + strcpy(test_argv[4], "3"); >>> + >>> + if (rte_eal_init(test_argc, (char **)test_argv) < 0) { >>> + ODP_ERR("Cannot init the Intel DPDK EAL!"); >>> + return -1; >>> + } >>> + >>> + if (rte_pmd_init_all() < 0) { >>> + ODP_ERR("Cannot init pmd\n"); >>> + return -1; >>> + } >>> + >>> + if (rte_eal_pci_probe() < 0) { >>> + ODP_ERR("Cannot probe PCI\n"); >>> + return -1; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +int odp_init_global(void) >>> +{ >>> + odp_thread_init_global(); >>> + >>> + odp_system_info_init(); >>> + >>> + if (odp_init_dpdk()) { >>> + ODP_ERR("ODP dpdk init failed.\n"); >>> + return -1; >>> + } >>> + >>> + if (odp_shm_init_global()) { >>> + ODP_ERR("ODP shm init failed.\n"); >>> + return -1; >>> + } >>> + >>> + if (odp_buffer_pool_init_global()) { >>> + ODP_ERR("ODP buffer pool init failed.\n"); >>> + return -1; >>> + } >>> + >>> + if (odp_queue_init_global()) { >>> + ODP_ERR("ODP queue init failed.\n"); >>> + return -1; >>> + } >>> + >>> + if (odp_schedule_init_global()) { >>> + ODP_ERR("ODP schedule init failed.\n"); >>> + return -1; >>> + } >>> + >>> + if (odp_pktio_init_global()) { >>> + ODP_ERR("ODP packet io init failed.\n"); >>> + return -1; >>> + } >>> + >>> + if (odp_timer_init_global()) { >>> + ODP_ERR("ODP timer init failed.\n"); >>> + return -1; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> + >>> +int odp_init_local(int thr_id) >>> +{ >>> + odp_thread_init_local(thr_id); >>> + >>> + if (odp_pktio_init_local()) { >>> + ODP_ERR("ODP packet io local init failed.\n"); >>> + return -1; >>> + } >>> + >>> + if (odp_schedule_init_local()) { >>> + ODP_ERR("ODP schedule local init failed.\n"); >>> + return -1; >>> + } >>> + >>> + return 0; >>> +} >>> diff --git a/platform/linux-dpdk/source/odp_packet.c >>> b/platform/linux-dpdk/source/odp_packet.c >>> new file mode 100644 >>> index 0000000..c34e626 >>> --- /dev/null >>> +++ b/platform/linux-dpdk/source/odp_packet.c >>> @@ -0,0 +1,374 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#include <odp_packet.h> >>> +#include <odp_packet_internal.h> >>> +#include <odp_hints.h> >>> +#include <odp_byteorder.h> >>> + >>> +#include <helper/odp_eth.h> >>> +#include <helper/odp_ip.h> >>> + >>> +#include <string.h> >>> +#include <stdio.h> >>> + >>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, >>> odp_ipv4hdr_t *ipv4, >>> + size_t *offset_out); >>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, >>> odp_ipv6hdr_t *ipv6, >>> + size_t *offset_out); >>> + >>> +void odp_packet_init(odp_packet_t pkt) >>> +{ >>> + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); >>> + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, >>> buf_hdr); >>> + uint8_t *start; >>> + size_t len; >>> + >>> + start = (uint8_t *)pkt_hdr + start_offset; >>> + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; >>> + memset(start, 0, len); >>> + >>> + pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >>> + pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >>> + pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >>> +} >>> + >>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf) >>> +{ >>> + return (odp_packet_t)buf; >>> +} >>> + >>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt) >>> +{ >>> + return (odp_buffer_t)pkt; >>> +} >>> + >>> +void odp_packet_set_len(odp_packet_t pkt, size_t len) >>> +{ >>> + /* for rte_pktmbuf */ >>> + odp_buffer_hdr_t *buf_hdr = >>> odp_buf_to_hdr(odp_buffer_from_packet(pkt)); >>> + buf_hdr->pkt.data_len = len; >>> + >>> + odp_packet_hdr(pkt)->frame_len = len; >>> +} >>> + >>> +size_t odp_packet_get_len(odp_packet_t pkt) >>> +{ >>> + return odp_packet_hdr(pkt)->frame_len; >>> +} >>> + >>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt) >>> +{ >>> + return odp_buffer_addr(odp_buffer_from_packet(pkt)); >>> +} >>> + >>> +uint8_t *odp_packet_start(odp_packet_t pkt) >>> +{ >>> + return odp_packet_buf_addr(pkt) + >>> odp_packet_hdr(pkt)->frame_offset; >>> +} >>> + >>> + >>> +uint8_t *odp_packet_l2(odp_packet_t pkt) >>> +{ >>> + const size_t offset = odp_packet_l2_offset(pkt); >>> + >>> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >>> + return NULL; >>> + >>> + return odp_packet_buf_addr(pkt) + offset; >>> +} >>> + >>> +size_t odp_packet_l2_offset(odp_packet_t pkt) >>> +{ >>> + return odp_packet_hdr(pkt)->l2_offset; >>> +} >>> + >>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset) >>> +{ >>> + odp_packet_hdr(pkt)->l2_offset = offset; >>> +} >>> + >>> +uint8_t *odp_packet_l3(odp_packet_t pkt) >>> +{ >>> + const size_t offset = odp_packet_l3_offset(pkt); >>> + >>> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >>> + return NULL; >>> + >>> + return odp_packet_buf_addr(pkt) + offset; >>> +} >>> + >>> +size_t odp_packet_l3_offset(odp_packet_t pkt) >>> +{ >>> + return odp_packet_hdr(pkt)->l3_offset; >>> +} >>> + >>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset) >>> +{ >>> + odp_packet_hdr(pkt)->l3_offset = offset; >>> +} >>> + >>> +uint8_t *odp_packet_l4(odp_packet_t pkt) >>> +{ >>> + const size_t offset = odp_packet_l4_offset(pkt); >>> + >>> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >>> + return NULL; >>> + >>> + return odp_packet_buf_addr(pkt) + offset; >>> +} >>> + >>> +size_t odp_packet_l4_offset(odp_packet_t pkt) >>> +{ >>> + return odp_packet_hdr(pkt)->l4_offset; >>> +} >>> + >>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset) >>> +{ >>> + odp_packet_hdr(pkt)->l4_offset = offset; >>> +} >>> + >>> +/** >>> + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP >>> + * >>> + * Internal function: caller is resposible for passing only valid >>> packet handles >>> + * , lengths and offsets (usually done&called in packet input). >>> + * >>> + * @param pkt Packet handle >>> + * @param len Packet length in bytes >>> + * @param frame_offset Byte offset to L2 header >>> + */ >>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset) >>> +{ >>> + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); >>> + odp_ethhdr_t *eth; >>> + odp_vlanhdr_t *vlan; >>> + odp_ipv4hdr_t *ipv4; >>> + odp_ipv6hdr_t *ipv6; >>> + uint16_t ethtype; >>> + size_t offset = 0; >>> + uint8_t ip_proto = 0; >>> + >>> + pkt_hdr->input_flags.eth = 1; >>> + pkt_hdr->frame_offset = frame_offset; >>> + pkt_hdr->frame_len = len; >>> + >>> + if (odp_unlikely(len < ODP_ETH_LEN_MIN)) { >>> + pkt_hdr->error_flags.frame_len = 1; >>> + return; >>> + } else if (len > ODP_ETH_LEN_MAX) { >>> + pkt_hdr->input_flags.jumbo = 1; >>> + } >>> + >>> + /* Assume valid L2 header, no CRC/FCS check in SW */ >>> + pkt_hdr->input_flags.l2 = 1; >>> + pkt_hdr->l2_offset = frame_offset; >>> + >>> + eth = (odp_ethhdr_t *)odp_packet_start(pkt); >>> + ethtype = odp_be_to_cpu_16(eth->type); >>> + vlan = (odp_vlanhdr_t *)ð->type; >>> + >>> + if (ethtype == ODP_ETHTYPE_VLAN_OUTER) { >>> + pkt_hdr->input_flags.vlan_qinq = 1; >>> + ethtype = odp_be_to_cpu_16(vlan->tpid); >>> + offset += sizeof(odp_vlanhdr_t); >>> + vlan = &vlan[1]; >>> + } >>> + >>> + if (ethtype == ODP_ETHTYPE_VLAN) { >>> + pkt_hdr->input_flags.vlan = 1; >>> + ethtype = odp_be_to_cpu_16(vlan->tpid); >>> + offset += sizeof(odp_vlanhdr_t); >>> + } >>> + >>> + /* Set l3_offset+flag only for known ethtypes */ >>> + switch (ethtype) { >>> + case ODP_ETHTYPE_IPV4: >>> + pkt_hdr->input_flags.ipv4 = 1; >>> + pkt_hdr->input_flags.l3 = 1; >>> + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + >>> offset; >>> + ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt); >>> + ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset); >>> + break; >>> + case ODP_ETHTYPE_IPV6: >>> + pkt_hdr->input_flags.ipv6 = 1; >>> + pkt_hdr->input_flags.l3 = 1; >>> + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + >>> offset; >>> + ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt); >>> + ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset); >>> + break; >>> + case ODP_ETHTYPE_ARP: >>> + pkt_hdr->input_flags.arp = 1; >>> + /* fall through */ >>> + default: >>> + ip_proto = 0; >>> + break; >>> + } >>> + >>> + switch (ip_proto) { >>> + case ODP_IPPROTO_UDP: >>> + pkt_hdr->input_flags.udp = 1; >>> + pkt_hdr->input_flags.l4 = 1; >>> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >>> + break; >>> + case ODP_IPPROTO_TCP: >>> + pkt_hdr->input_flags.tcp = 1; >>> + pkt_hdr->input_flags.l4 = 1; >>> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >>> + break; >>> + case ODP_IPPROTO_SCTP: >>> + pkt_hdr->input_flags.sctp = 1; >>> + pkt_hdr->input_flags.l4 = 1; >>> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >>> + break; >>> + case ODP_IPPROTO_ICMP: >>> + pkt_hdr->input_flags.icmp = 1; >>> + pkt_hdr->input_flags.l4 = 1; >>> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >>> + break; >>> + default: >>> + /* 0 or unhandled IP protocols, don't set L4 flag+offset >>> */ >>> + if (pkt_hdr->input_flags.ipv6) { >>> + /* IPv6 next_hdr is not L4, mark as IP-option >>> instead */ >>> + pkt_hdr->input_flags.ipopt = 1; >>> + } >>> + break; >>> + } >>> +} >>> + >>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, >>> odp_ipv4hdr_t *ipv4, >>> + size_t *offset_out) >>> +{ >>> + uint8_t ihl; >>> + uint16_t frag_offset; >>> + >>> + ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl); >>> + if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) { >>> + pkt_hdr->error_flags.ip_err = 1; >>> + return 0; >>> + } >>> + >>> + if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) { >>> + pkt_hdr->input_flags.ipopt = 1; >>> + return 0; >>> + } >>> + >>> + /* A packet is a fragment if: >>> + * "more fragments" flag is set (all fragments except the last) >>> + * OR >>> + * "fragment offset" field is nonzero (all fragments except the >>> first) >>> + */ >>> + frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); >>> + if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) { >>> + pkt_hdr->input_flags.ipfrag = 1; >>> + return 0; >>> + } >>> + >>> + if (ipv4->proto == ODP_IPPROTO_ESP || >>> + ipv4->proto == ODP_IPPROTO_AH) { >>> + pkt_hdr->input_flags.ipsec = 1; >>> + return 0; >>> + } >>> + >>> + /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after >>> return */ >>> + >>> + *offset_out = sizeof(uint32_t) * ihl; >>> + return ipv4->proto; >>> +} >>> + >>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, >>> odp_ipv6hdr_t *ipv6, >>> + size_t *offset_out) >>> +{ >>> + if (ipv6->next_hdr == ODP_IPPROTO_ESP || >>> + ipv6->next_hdr == ODP_IPPROTO_AH) { >>> + pkt_hdr->input_flags.ipopt = 1; >>> + pkt_hdr->input_flags.ipsec = 1; >>> + return 0; >>> + } >>> + >>> + if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) { >>> + pkt_hdr->input_flags.ipopt = 1; >>> + pkt_hdr->input_flags.ipfrag = 1; >>> + return 0; >>> + } >>> + >>> + /* Don't step through more extensions */ >>> + *offset_out = ODP_IPV6HDR_LEN; >>> + return ipv6->next_hdr; >>> +} >>> + >>> +void odp_packet_print(odp_packet_t pkt) >>> +{ >>> + int max_len = 512; >>> + char str[max_len]; >>> + int len = 0; >>> + int n = max_len-1; >>> + odp_packet_hdr_t *hdr = odp_packet_hdr(pkt); >>> + >>> + len += snprintf(&str[len], n-len, "Packet "); >>> + len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt); >>> + len += snprintf(&str[len], n-len, >>> + " input_flags 0x%x\n", hdr->input_flags.all); >>> + len += snprintf(&str[len], n-len, >>> + " error_flags 0x%x\n", hdr->error_flags.all); >>> + len += snprintf(&str[len], n-len, >>> + " output_flags 0x%x\n", hdr->output_flags.all); >>> + len += snprintf(&str[len], n-len, >>> + " frame_offset %u\n", hdr->frame_offset); >>> + len += snprintf(&str[len], n-len, >>> + " l2_offset %u\n", hdr->l2_offset); >>> + len += snprintf(&str[len], n-len, >>> + " l3_offset %u\n", hdr->l3_offset); >>> + len += snprintf(&str[len], n-len, >>> + " l4_offset %u\n", hdr->l4_offset); >>> + len += snprintf(&str[len], n-len, >>> + " frame_len %u\n", hdr->frame_len); >>> + len += snprintf(&str[len], n-len, >>> + " input %u\n", hdr->input); >>> + str[len] = '\0'; >>> + >>> + printf("\n%s\n", str); >>> +} >>> + >>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src) >>> +{ >>> + odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst); >>> + odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src); >>> + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, >>> buf_hdr); >>> + uint8_t *start_src; >>> + uint8_t *start_dst; >>> + size_t len; >>> + >>> + if (pkt_dst == ODP_PACKET_INVALID || pkt_src == >>> ODP_PACKET_INVALID) >>> + return -1; >>> + >>> + /* if (pkt_hdr_dst->buf_hdr.size < */ >>> + /* pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */ >>> + if (pkt_hdr_dst->buf_hdr.buf_len < >>> + pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) >>> + return -1; >>> + >>> + /* Copy packet header */ >>> + start_dst = (uint8_t *)pkt_hdr_dst + start_offset; >>> + start_src = (uint8_t *)pkt_hdr_src + start_offset; >>> + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; >>> + memcpy(start_dst, start_src, len); >>> + >>> + /* Copy frame payload */ >>> + start_dst = (uint8_t *)odp_packet_start(pkt_dst); >>> + start_src = (uint8_t *)odp_packet_start(pkt_src); >>> + len = pkt_hdr_src->frame_len; >>> + memcpy(start_dst, start_src, len); >>> + >>> + /* Copy useful things from the buffer header */ >>> + /* pkt_hdr_dst->buf_hdr.cur_offset = >>> pkt_hdr_src->buf_hdr.cur_offset; */ >>> + >>> + /* Create a copy of the scatter list */ >>> + /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */ >>> + /* odp_buffer_from_packet(pkt_src)); */ >>> + >>> + return 0; >>> +} >>> diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c >>> b/platform/linux-dpdk/source/odp_packet_dpdk.c >>> new file mode 100644 >>> index 0000000..6d16bbe >>> --- /dev/null >>> +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c >>> @@ -0,0 +1,177 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#define _GNU_SOURCE >>> +#include <stdio.h> >>> +#include <errno.h> >>> +#include <sys/types.h> >>> +#include <sys/stat.h> >>> +#include <sys/ioctl.h> >>> +#include <sys/mman.h> >>> +#include <poll.h> >>> +#include <unistd.h> >>> +#include <fcntl.h> >>> +#include <string.h> >>> +#include <stdlib.h> >>> + >>> +#include <linux/ethtool.h> >>> +#include <linux/sockios.h> >>> + >>> +#include <odp_hints.h> >>> +#include <odp_thread.h> >>> + >>> +#include <odp_packet_dpdk.h> >>> +#include <net/if.h> >>> + >>> +/* >>> + * RX and TX Prefetch, Host, and Write-back threshold values should be >>> + * carefully set for optimal performance. Consult the network >>> + * controller's datasheet and supporting DPDK documentation for guidance >>> + * on how these parameters should be set. >>> + */ >>> +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. >>> */ >>> +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ >>> +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold >>> reg. */ >>> + >>> +/* >>> + * These default values are optimized for use with the Intel(R) 82599 >>> 10 GbE >>> + * Controller and the DPDK ixgbe PMD. Consider using other values for >>> other >>> + * network controllers and/or network drivers. >>> + */ >>> +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. >>> */ >>> +#define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ >>> +#define TX_WTHRESH 0 /**< Default values of TX write-back threshold >>> reg. */ >>> + >>> +#define MAX_PKT_BURST 32 >>> +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ >>> +#define RTE_TEST_RX_DESC_DEFAULT 128 >>> +#define RTE_TEST_TX_DESC_DEFAULT 512 >>> +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; >>> +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; >>> + >>> +static const struct rte_eth_conf port_conf = { >>> + .rxmode = { >>> + .split_hdr_size = 0, >>> + .header_split = 0, /**< Header Split disabled */ >>> + .hw_ip_checksum = 0, /**< IP checksum offload disabled */ >>> + .hw_vlan_filter = 0, /**< VLAN filtering disabled */ >>> + .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ >>> + .hw_strip_crc = 0, /**< CRC stripped by hardware */ >>> + }, >>> + .txmode = { >>> + .mq_mode = ETH_MQ_TX_NONE, >>> + }, >>> +}; >>> + >>> +static const struct rte_eth_rxconf rx_conf = { >>> + .rx_thresh = { >>> + .pthresh = RX_PTHRESH, >>> + .hthresh = RX_HTHRESH, >>> + .wthresh = RX_WTHRESH, >>> + }, >>> +}; >>> + >>> +static const struct rte_eth_txconf tx_conf = { >>> + .tx_thresh = { >>> + .pthresh = TX_PTHRESH, >>> + .hthresh = TX_HTHRESH, >>> + .wthresh = TX_WTHRESH, >>> + }, >>> + .tx_free_thresh = 0, /* Use PMD default values */ >>> + .tx_rs_thresh = 0, /* Use PMD default values */ >>> + /* >>> + * As the example won't handle mult-segments and offload cases, >>> + * set the flag by default. >>> + */ >>> + .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, >>> +}; >>> + >>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, >>> + odp_buffer_pool_t pool) >>> +{ >>> + ODP_DBG("setup_pkt_dpdk\n"); >>> + >>> + static struct ether_addr eth_addr[RTE_MAX_ETHPORTS]; >>> + uint8_t portid = 0; >>> + uint16_t queueid = 0; >>> + int ret; >>> + printf("vincent netdev: %s\n", netdev); >>> + printf("vincent pool: %lx\n", pool); >>> + >>> + portid = atoi(netdev); >>> + pkt_dpdk->portid = portid; >>> + pkt_dpdk->queueid = queueid; >>> + pkt_dpdk->pool = pool; >>> + printf("vincent portid: %u\n", portid); >>> + >>> + fflush(stdout); >>> + ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); >>> + if (ret < 0) >>> + ODP_ERR("Cannot configure device: err=%d, port=%u\n", >>> + ret, (unsigned) portid); >>> + >>> + rte_eth_macaddr_get(portid, ð_addr[portid]); >>> + ODP_DBG("Port %u, MAC address: >>> %02X:%02X:%02X:%02X:%02X:%02X\n\n", >>> + (unsigned) portid, >>> + eth_addr[portid].addr_bytes[0], >>> + eth_addr[portid].addr_bytes[1], >>> + eth_addr[portid].addr_bytes[2], >>> + eth_addr[portid].addr_bytes[3], >>> + eth_addr[portid].addr_bytes[4], >>> + eth_addr[portid].addr_bytes[5]); >>> + >>> + /* init one RX queue on each port */ >>> + fflush(stdout); >>> + ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, >>> + rte_eth_dev_socket_id(portid), >>> &rx_conf, >>> + (struct rte_mempool *)pool); >>> + if (ret < 0) >>> + ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n", >>> + ret, (unsigned) portid); >>> + ODP_DBG("dpdk rx queue setup done\n"); >>> + >>> + /* init one TX queue on each port */ >>> + fflush(stdout); >>> + ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, >>> + rte_eth_dev_socket_id(portid), &tx_conf); >>> + if (ret < 0) >>> + ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n", >>> + ret, (unsigned) portid); >>> + ODP_DBG("dpdk tx queue setup done\n"); >>> + >>> + /* Start device */ >>> + ret = rte_eth_dev_start(portid); >>> + if (ret < 0) >>> + ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n", >>> + ret, (unsigned) portid); >>> + ODP_DBG("dpdk setup done\n\n"); >>> + >>> + >>> + return 0; >>> +} >>> + >>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk) >>> +{ >>> + ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid); >>> + >>> + return 0; >>> +} >>> + >>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], >>> + unsigned len) >>> +{ >>> + return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid, >>> + (uint16_t)pkt_dpdk->queueid, >>> + (struct rte_mbuf **)pkt_table, >>> (uint16_t)len); >>> +} >>> + >>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], >>> + unsigned len) >>> +{ >>> + return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid, >>> + (uint16_t)pkt_dpdk->queueid, >>> + (struct rte_mbuf **)pkt_table, >>> (uint16_t)len); >>> +} >>> diff --git a/platform/linux-dpdk/source/odp_packet_io.c >>> b/platform/linux-dpdk/source/odp_packet_io.c >>> new file mode 100644 >>> index 0000000..abea0ec >>> --- /dev/null >>> +++ b/platform/linux-dpdk/source/odp_packet_io.c >>> @@ -0,0 +1,561 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#include <odp_packet_io.h> >>> +#include <odp_packet_io_internal.h> >>> +#include <odp_packet_io_queue.h> >>> +#include <odp_packet.h> >>> +#include <odp_packet_internal.h> >>> +#include <odp_internal.h> >>> +#include <odp_spinlock.h> >>> +#include <odp_shared_memory.h> >>> +#include <odp_packet_socket.h> >>> +#ifdef ODP_HAVE_NETMAP >>> +#include <odp_packet_netmap.h> >>> +#endif >>> +#include <odp_hints.h> >>> +#include <odp_config.h> >>> +#include <odp_queue_internal.h> >>> +#include <odp_schedule_internal.h> >>> +#include <odp_debug.h> >>> + >>> +#include <odp_pktio_socket.h> >>> +#ifdef ODP_HAVE_NETMAP >>> +#include <odp_pktio_netmap.h> >>> +#endif >>> + >>> +#include <string.h> >>> + >>> +typedef struct { >>> + pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES]; >>> +} pktio_table_t; >>> + >>> +static pktio_table_t *pktio_tbl; >>> + >>> + >>> +static pktio_entry_t *get_entry(odp_pktio_t id) >>> +{ >>> + if (odp_unlikely(id == ODP_PKTIO_INVALID || >>> + id > ODP_CONFIG_PKTIO_ENTRIES)) >>> + return NULL; >>> + >>> + return &pktio_tbl->entries[id - 1]; >>> +} >>> + >>> +int odp_pktio_init_global(void) >>> +{ >>> + char name[ODP_QUEUE_NAME_LEN]; >>> + pktio_entry_t *pktio_entry; >>> + queue_entry_t *queue_entry; >>> + odp_queue_t qid; >>> + int id; >>> + >>> + pktio_tbl = odp_shm_reserve("odp_pktio_entries", >>> + sizeof(pktio_table_t), >>> + sizeof(pktio_entry_t)); >>> + if (pktio_tbl == NULL) >>> + return -1; >>> + >>> + memset(pktio_tbl, 0, sizeof(pktio_table_t)); >>> + >>> + for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) { >>> + pktio_entry = get_entry(id); >>> + >>> + odp_spinlock_init(&pktio_entry->s.lock); >>> + >>> + /* Create a default output queue for each pktio resource >>> */ >>> + snprintf(name, sizeof(name), "%i-pktio_outq_default", >>> (int)id); >>> + name[ODP_QUEUE_NAME_LEN-1] = '\0'; >>> + >>> + qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, >>> NULL); >>> + if (qid == ODP_QUEUE_INVALID) >>> + return -1; >>> + pktio_entry->s.outq_default = qid; >>> + >>> + queue_entry = queue_to_qentry(qid); >>> + queue_entry->s.pktout = id; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +int odp_pktio_init_local(void) >>> +{ >>> + return 0; >>> +} >>> + >>> +static int is_free(pktio_entry_t *entry) >>> +{ >>> + return (entry->s.taken == 0); >>> +} >>> + >>> +static void set_free(pktio_entry_t *entry) >>> +{ >>> + entry->s.taken = 0; >>> +} >>> + >>> +static void set_taken(pktio_entry_t *entry) >>> +{ >>> + entry->s.taken = 1; >>> +} >>> + >>> +static void lock_entry(pktio_entry_t *entry) >>> +{ >>> + odp_spinlock_lock(&entry->s.lock); >>> +} >>> + >>> +static void unlock_entry(pktio_entry_t *entry) >>> +{ >>> + odp_spinlock_unlock(&entry->s.lock); >>> +} >>> + >>> +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t >>> *params) >>> +{ >>> + set_taken(entry); >>> + entry->s.inq_default = ODP_QUEUE_INVALID; >>> + switch (params->type) { >>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>> + memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock)); >>> + memset(&entry->s.pkt_sock_mmap, 0, >>> + sizeof(entry->s.pkt_sock_mmap)); >>> + break; >>> +#ifdef ODP_HAVE_NETMAP >>> + case ODP_PKTIO_TYPE_NETMAP: >>> + memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm)); >>> + break; >>> +#endif >>> + case ODP_PKTIO_TYPE_DPDK: >>> + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); >>> + break; >>> + default: >>> + ODP_ERR("Packet I/O type not supported. Please >>> recompile\n"); >>> + break; >>> + } >>> + /* Save pktio parameters, type is the most useful */ >>> + memcpy(&entry->s.params, params, sizeof(*params)); >>> +} >>> + >>> +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params) >>> +{ >>> + odp_pktio_t id; >>> + pktio_entry_t *entry; >>> + int i; >>> + >>> + for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) { >>> + entry = &pktio_tbl->entries[i]; >>> + if (is_free(entry)) { >>> + lock_entry(entry); >>> + if (is_free(entry)) { >>> + init_pktio_entry(entry, params); >>> + id = i + 1; >>> + return id; /* return with entry locked! >>> */ >>> + } >>> + unlock_entry(entry); >>> + } >>> + } >>> + >>> + return ODP_PKTIO_INVALID; >>> +} >>> + >>> +static int free_pktio_entry(odp_pktio_t id) >>> +{ >>> + pktio_entry_t *entry = get_entry(id); >>> + >>> + if (entry == NULL) >>> + return -1; >>> + >>> + set_free(entry); >>> + >>> + return 0; >>> +} >>> + >>> +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool, >>> + odp_pktio_params_t *params) >>> +{ >>> + odp_pktio_t id; >>> + pktio_entry_t *pktio_entry; >>> + int res; >>> + >>> + if (params == NULL) { >>> + ODP_ERR("Invalid pktio params\n"); >>> + return ODP_PKTIO_INVALID; >>> + } >>> + >>> + switch (params->type) { >>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>> + ODP_DBG("Allocating socket pktio\n"); >>> + break; >>> +#ifdef ODP_HAVE_NETMAP >>> + case ODP_PKTIO_TYPE_NETMAP: >>> + ODP_DBG("Allocating netmap pktio\n"); >>> + break; >>> +#endif >>> + case ODP_PKTIO_TYPE_DPDK: >>> + ODP_DBG("Allocating dpdk pktio\n"); >>> + break; >>> + default: >>> + ODP_ERR("Invalid pktio type: %02x\n", params->type); >>> + return ODP_PKTIO_INVALID; >>> + } >>> + >>> + id = alloc_lock_pktio_entry(params); >>> + if (id == ODP_PKTIO_INVALID) { >>> + ODP_ERR("No resources available.\n"); >>> + return ODP_PKTIO_INVALID; >>> + } >>> + /* if successful, alloc_pktio_entry() returns with the entry >>> locked */ >>> + >>> + pktio_entry = get_entry(id); >>> + >>> + switch (params->type) { >>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>> + res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, >>> pool); >>> + if (res == -1) { >>> + close_pkt_sock(&pktio_entry->s.pkt_sock); >>> + free_pktio_entry(id); >>> + id = ODP_PKTIO_INVALID; >>> + } >>> + break; >>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>> + res = setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, >>> dev, >>> + pool, params->sock_params.fanout); >>> + if (res == -1) { >>> + >>> close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap); >>> + free_pktio_entry(id); >>> + id = ODP_PKTIO_INVALID; >>> + } >>> + break; >>> +#ifdef ODP_HAVE_NETMAP >>> + case ODP_PKTIO_TYPE_NETMAP: >>> + >>> + res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev, >>> + pool, ¶ms->nm_params); >>> + if (res == -1) { >>> + close_pkt_netmap(&pktio_entry->s.pkt_nm); >>> + free_pktio_entry(id); >>> + id = ODP_PKTIO_INVALID; >>> + } >>> + break; >>> +#endif >>> + case ODP_PKTIO_TYPE_DPDK: >>> + res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, >>> pool); >>> + if (res == -1) { >>> + close_pkt_dpdk(&pktio_entry->s.pkt_dpdk); >>> + free_pktio_entry(id); >>> + id = ODP_PKTIO_INVALID; >>> + } >>> + break; >>> + default: >>> + free_pktio_entry(id); >>> + id = ODP_PKTIO_INVALID; >>> + ODP_ERR("Invalid pktio type. Please recompile.\n"); >>> + break; >>> + } >>> + >>> + unlock_entry(pktio_entry); >>> + return id; >>> +} >>> + >>> +int odp_pktio_close(odp_pktio_t id) >>> +{ >>> + pktio_entry_t *entry; >>> + int res = -1; >>> + >>> + entry = get_entry(id); >>> + if (entry == NULL) >>> + return -1; >>> + >>> + lock_entry(entry); >>> + if (!is_free(entry)) { >>> + switch (entry->s.params.type) { >>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>> + res = close_pkt_sock(&entry->s.pkt_sock); >>> + break; >>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>> + res = >>> close_pkt_sock_mmap(&entry->s.pkt_sock_mmap); >>> + break; >>> +#ifdef ODP_HAVE_NETMAP >>> + case ODP_PKTIO_TYPE_NETMAP: >>> + res = close_pkt_netmap(&entry->s.pkt_nm); >>> + break; >>> +#endif >>> + case ODP_PKTIO_TYPE_DPDK: >>> + res = close_pkt_dpdk(&entry->s.pkt_dpdk); >>> + break; >>> + default: >>> + break; >>> + res |= free_pktio_entry(id); >>> + } >>> + } >>> + unlock_entry(entry); >>> + >>> + if (res != 0) >>> + return -1; >>> + >>> + return 0; >>> +} >>> + >>> +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio) >>> +{ >>> + odp_packet_hdr(pkt)->input = pktio; >>> +} >>> + >>> +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt) >>> +{ >>> + return odp_packet_hdr(pkt)->input; >>> +} >>> + >>> +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned >>> len) >>> +{ >>> + pktio_entry_t *pktio_entry = get_entry(id); >>> + int pkts; >>> + int i; >>> + >>> + if (pktio_entry == NULL) >>> + return -1; >>> + >>> + lock_entry(pktio_entry); >>> + switch (pktio_entry->s.params.type) { >>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>> + pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock, >>> + pkt_table, len); >>> + break; >>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>> + pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, >>> + pkt_table, len); >>> + break; >>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>> + pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, >>> + pkt_table, len); >>> + break; >>> +#ifdef ODP_HAVE_NETMAP >>> + case ODP_PKTIO_TYPE_NETMAP: >>> + pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm, >>> pkt_table, len); >>> + break; >>> +#endif >>> + case ODP_PKTIO_TYPE_DPDK: >>> + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, >>> pkt_table, len); >>> + break; >>> + default: >>> + pkts = -1; >>> + break; >>> + } >>> + >>> + unlock_entry(pktio_entry); >>> + if (pkts < 0) >>> + return pkts; >>> + >>> + for (i = 0; i < pkts; ++i) >>> + odp_pktio_set_input(pkt_table[i], id); >>> + >>> + return pkts; >>> +} >>> + >>> +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned >>> len) >>> +{ >>> + pktio_entry_t *pktio_entry = get_entry(id); >>> + int pkts; >>> + >>> + if (pktio_entry == NULL) >>> + return -1; >>> + >>> + lock_entry(pktio_entry); >>> + switch (pktio_entry->s.params.type) { >>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>> + pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock, >>> + pkt_table, len); >>> + break; >>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>> + pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, >>> + pkt_table, len); >>> + break; >>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>> + pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, >>> + pkt_table, len); >>> + break; >>> +#ifdef ODP_HAVE_NETMAP >>> + case ODP_PKTIO_TYPE_NETMAP: >>> + pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm, >>> + pkt_table, len); >>> + break; >>> +#endif >>> + case ODP_PKTIO_TYPE_DPDK: >>> + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, >>> + pkt_table, len); >>> + break; >>> + default: >>> + pkts = -1; >>> + } >>> + unlock_entry(pktio_entry); >>> + >>> + return pkts; >>> +} >>> + >>> +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue) >>> +{ >>> + pktio_entry_t *pktio_entry = get_entry(id); >>> + queue_entry_t *qentry = queue_to_qentry(queue); >>> + >>> + if (pktio_entry == NULL || qentry == NULL) >>> + return -1; >>> + >>> + if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN) >>> + return -1; >>> + >>> + lock_entry(pktio_entry); >>> + pktio_entry->s.inq_default = queue; >>> + unlock_entry(pktio_entry); >>> + >>> + queue_lock(qentry); >>> + qentry->s.pktin = id; >>> + qentry->s.status = QUEUE_STATUS_SCHED; >>> + queue_unlock(qentry); >>> + >>> + odp_schedule_queue(queue, qentry->s.param.sched.prio); >>> + >>> + return 0; >>> +} >>> + >>> +int odp_pktio_inq_remdef(odp_pktio_t id) >>> +{ >>> + return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID); >>> +} >>> + >>> +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id) >>> +{ >>> + pktio_entry_t *pktio_entry = get_entry(id); >>> + >>> + if (pktio_entry == NULL) >>> + return ODP_QUEUE_INVALID; >>> + >>> + return pktio_entry->s.inq_default; >>> +} >>> + >>> +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id) >>> +{ >>> + pktio_entry_t *pktio_entry = get_entry(id); >>> + >>> + if (pktio_entry == NULL) >>> + return ODP_QUEUE_INVALID; >>> + >>> + return pktio_entry->s.outq_default; >>> +} >>> + >>> +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) >>> +{ >>> + odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t) >>> buf_hdr); >>> + int len = 1; >>> + int nbr; >>> + >>> + nbr = odp_pktio_send(qentry->s.pktout, &pkt, len); >>> + return (nbr == len ? 0 : -1); >>> +} >>> + >>> +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry) >>> +{ >>> + (void)qentry; >>> + return NULL; >>> +} >>> + >>> +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], >>> + int num) >>> +{ >>> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >>> + int nbr; >>> + int i; >>> + >>> + for (i = 0; i < num; ++i) >>> + pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t) >>> buf_hdr[i]); >>> + >>> + nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num); >>> + return (nbr == num ? 0 : -1); >>> +} >>> + >>> +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], >>> + int num) >>> +{ >>> + (void)qentry; >>> + (void)buf_hdr; >>> + (void)num; >>> + >>> + return 0; >>> +} >>> + >>> +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) >>> +{ >>> + /* Use default action */ >>> + return queue_enq(qentry, buf_hdr); >>> +} >>> + >>> +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry) >>> +{ >>> + odp_buffer_hdr_t *buf_hdr; >>> + >>> + buf_hdr = queue_deq(qentry); >>> + >>> + if (buf_hdr == NULL) { >>> + odp_packet_t pkt; >>> + odp_buffer_t buf; >>> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >>> + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; >>> + int pkts, i, j; >>> + >>> + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, >>> + QUEUE_MULTI_MAX); >>> + >>> + if (pkts > 0) { >>> + pkt = pkt_tbl[0]; >>> + buf = odp_buffer_from_packet(pkt); >>> + buf_hdr = odp_buf_to_hdr(buf); >>> + >>> + for (i = 1, j = 0; i < pkts; ++i) { >>> + buf = odp_buffer_from_packet(pkt_tbl[i]); >>> + tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf); >>> + } >>> + queue_enq_multi(qentry, tmp_hdr_tbl, j); >>> + } >>> + } >>> + >>> + return buf_hdr; >>> +} >>> + >>> +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], >>> int num) >>> +{ >>> + /* Use default action */ >>> + return queue_enq_multi(qentry, buf_hdr, num); >>> +} >>> + >>> +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], >>> int num) >>> +{ >>> + int nbr; >>> + >>> + nbr = queue_deq_multi(qentry, buf_hdr, num); >>> + >>> + if (nbr < num) { >>> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >>> + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; >>> + odp_buffer_t buf; >>> + int pkts, i; >>> + >>> + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, >>> + QUEUE_MULTI_MAX); >>> + if (pkts > 0) { >>> + for (i = 0; i < pkts; ++i) { >>> + buf = odp_buffer_from_packet(pkt_tbl[i]); >>> + tmp_hdr_tbl[i] = odp_buf_to_hdr(buf); >>> + } >>> + queue_enq_multi(qentry, tmp_hdr_tbl, pkts); >>> + } >>> + } >>> + >>> + return nbr; >>> +} >>> diff --git a/platform/linux-dpdk/source/odp_queue.c >>> b/platform/linux-dpdk/source/odp_queue.c >>> new file mode 100644 >>> index 0000000..554b8ea >>> --- /dev/null >>> +++ b/platform/linux-dpdk/source/odp_queue.c >>> @@ -0,0 +1,435 @@ >>> +/* Copyright (c) 2013, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#include <odp_queue.h> >>> +#include <odp_queue_internal.h> >>> +#include <odp_std_types.h> >>> +#include <odp_align.h> >>> +#include <odp_buffer.h> >>> +#include <odp_buffer_internal.h> >>> +#include <odp_buffer_pool_internal.h> >>> +#include <odp_internal.h> >>> +#include <odp_shared_memory.h> >>> +#include <odp_schedule_internal.h> >>> +#include <odp_config.h> >>> +#include <odp_packet_io_internal.h> >>> +#include <odp_packet_io_queue.h> >>> +#include <odp_debug.h> >>> +#include <odp_hints.h> >>> + >>> +#ifdef USE_TICKETLOCK >>> +#include <odp_ticketlock.h> >>> +#define LOCK(a) odp_ticketlock_lock(a) >>> +#define UNLOCK(a) odp_ticketlock_unlock(a) >>> +#define LOCK_INIT(a) odp_ticketlock_init(a) >>> +#else >>> +#include <odp_spinlock.h> >>> +#define LOCK(a) odp_spinlock_lock(a) >>> +#define UNLOCK(a) odp_spinlock_unlock(a) >>> +#define LOCK_INIT(a) odp_spinlock_init(a) >>> +#endif >>> + >>> +#include <string.h> >>> + >>> + >>> +typedef struct queue_table_t { >>> + queue_entry_t queue[ODP_CONFIG_QUEUES]; >>> +} queue_table_t; >>> + >>> +static queue_table_t *queue_tbl; >>> + >>> + >>> +queue_entry_t *get_qentry(uint32_t queue_id) >>> +{ >>> + return &queue_tbl->queue[queue_id]; >>> +} >>> + >>> +static void queue_init(queue_entry_t *queue, const char *name, >>> + odp_queue_type_t type, odp_queue_param_t *param) >>> +{ >>> + strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1); >>> + queue->s.type = type; >>> + >>> + if (param) { >>> + memcpy(&queue->s.param, param, >>> sizeof(odp_queue_param_t)); >>> + } else { >>> + /* Defaults */ >>> + memset(&queue->s.param, 0, sizeof(odp_queue_param_t)); >>> + queue->s.param.sched.prio = ODP_SCHED_PRIO_DEFAULT; >>> + queue->s.param.sched.sync = ODP_SCHED_SYNC_DEFAULT; >>> + queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT; >>> + } >>> + >>> + switch (type) { >>> + case ODP_QUEUE_TYPE_PKTIN: >>> + queue->s.enqueue = pktin_enqueue; >>> + queue->s.dequeue = pktin_dequeue; >>> + queue->s.enqueue_multi = pktin_enq_multi; >>> + queue->s.dequeue_multi = pktin_deq_multi; >>> + break; >>> + case ODP_QUEUE_TYPE_PKTOUT: >>> + queue->s.enqueue = pktout_enqueue; >>> + queue->s.dequeue = pktout_dequeue; >>> + queue->s.enqueue_multi = pktout_enq_multi; >>> + queue->s.dequeue_multi = pktout_deq_multi; >>> + break; >>> + default: >>> + queue->s.enqueue = queue_enq; >>> + queue->s.dequeue = queue_deq; >>> + queue->s.enqueue_multi = queue_enq_multi; >>> + queue->s.dequeue_multi = queue_deq_multi; >>> + break; >>> + } >>> + >>> + queue->s.head = NULL; >>> + queue->s.tail = NULL; >>> + queue->s.sched_buf = ODP_BUFFER_INVALID; >>> +} >>> + >>> + >>> +int odp_queue_init_global(void) >>> +{ >>> + uint32_t i; >>> + >>> + ODP_DBG("Queue init ... "); >>> + >>> + queue_tbl = odp_shm_reserve("odp_queues", >>> + sizeof(queue_table_t), >>> + sizeof(queue_entry_t)); >>> + >>> + if (queue_tbl == NULL) >>> + return -1; >>> + >>> + memset(queue_tbl, 0, sizeof(queue_table_t)); >>> + >>> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >>> + /* init locks */ >>> + queue_entry_t *queue = get_qentry(i); >>> + LOCK_INIT(&queue->s.lock); >>> + queue->s.handle = queue_from_id(i); >>> + } >>> + >>> + ODP_DBG("done\n"); >>> + ODP_DBG("Queue init global\n"); >>> + ODP_DBG(" struct queue_entry_s size %zu\n", >>> + sizeof(struct queue_entry_s)); >>> + ODP_DBG(" queue_entry_t size %zu\n", >>> + sizeof(queue_entry_t)); >>> + ODP_DBG("\n"); >>> + >>> + return 0; >>> +} >>> + >>> +odp_queue_type_t odp_queue_type(odp_queue_t handle) >>> +{ >>> + queue_entry_t *queue; >>> + >>> + queue = queue_to_qentry(handle); >>> + >>> + return queue->s.type; >>> +} >>> + >>> +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle) >>> +{ >>> + queue_entry_t *queue; >>> + >>> + queue = queue_to_qentry(handle); >>> + >>> + return queue->s.param.sched.sync; >>> +} >>> + >>> +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type, >>> + odp_queue_param_t *param) >>> +{ >>> + uint32_t i; >>> + queue_entry_t *queue; >>> + odp_queue_t handle = ODP_QUEUE_INVALID; >>> + >>> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >>> + queue = &queue_tbl->queue[i]; >>> + >>> + if (queue->s.status != QUEUE_STATUS_FREE) >>> + continue; >>> + >>> + LOCK(&queue->s.lock); >>> + if (queue->s.status == QUEUE_STATUS_FREE) { >>> + queue_init(queue, name, type, param); >>> + >>> + if (type == ODP_QUEUE_TYPE_SCHED || >>> + type == ODP_QUEUE_TYPE_PKTIN) >>> + queue->s.status = QUEUE_STATUS_NOTSCHED; >>> + else >>> + queue->s.status = QUEUE_STATUS_READY; >>> + >>> + handle = queue->s.handle; >>> + UNLOCK(&queue->s.lock); >>> + break; >>> + } >>> + UNLOCK(&queue->s.lock); >>> + } >>> + >>> + if (handle != ODP_QUEUE_INVALID && >>> + (type == ODP_QUEUE_TYPE_SCHED || type == >>> ODP_QUEUE_TYPE_PKTIN)) { >>> + odp_buffer_t buf; >>> + >>> + buf = odp_schedule_buffer_alloc(handle); >>> + if (buf == ODP_BUFFER_INVALID) { >>> + ODP_ERR("queue_init: sched buf alloc failed\n"); >>> + return ODP_QUEUE_INVALID; >>> + } >>> + >>> + queue->s.sched_buf = buf; >>> + odp_schedule_mask_set(handle, queue->s.param.sched.prio); >>> + } >>> + >>> + return handle; >>> +} >>> + >>> + >>> +odp_buffer_t queue_sched_buf(odp_queue_t handle) >>> +{ >>> + queue_entry_t *queue; >>> + queue = queue_to_qentry(handle); >>> + >>> + return queue->s.sched_buf; >>> +} >>> + >>> + >>> +int queue_sched_atomic(odp_queue_t handle) >>> +{ >>> + queue_entry_t *queue; >>> + queue = queue_to_qentry(handle); >>> + >>> + return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC; >>> +} >>> + >>> + >>> +odp_queue_t odp_queue_lookup(const char *name) >>> +{ >>> + uint32_t i; >>> + >>> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >>> + queue_entry_t *queue = &queue_tbl->queue[i]; >>> + >>> + if (queue->s.status == QUEUE_STATUS_FREE) >>> + continue; >>> + >>> + LOCK(&queue->s.lock); >>> + if (strcmp(name, queue->s.name) == 0) { >>> + /* found it */ >>> + UNLOCK(&queue->s.lock); >>> + return queue->s.handle; >>> + } >>> + UNLOCK(&queue->s.lock); >>> + } >>> + >>> + return ODP_QUEUE_INVALID; >>> +} >>> + >>> + >>> +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr) >>> +{ >>> + int sched = 0; >>> + >>> + LOCK(&queue->s.lock); >>> + if (queue->s.head == NULL) { >>> + /* Empty queue */ >>> + queue->s.head = buf_hdr; >>> + queue->s.tail = buf_hdr; >>> + buf_hdr->pkt.next = NULL; >>> + } else { >>> + queue->s.tail->pkt.next = buf_hdr; >>> + queue->s.tail = buf_hdr; >>> + buf_hdr->pkt.next = NULL; >>> + } >>> + >>> + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { >>> + queue->s.status = QUEUE_STATUS_SCHED; >>> + sched = 1; /* retval: schedule queue */ >>> + } >>> + UNLOCK(&queue->s.lock); >>> + >>> + /* Add queue to scheduling */ >>> + if (sched == 1) >>> + odp_schedule_queue(queue->s.handle, >>> queue->s.param.sched.prio); >>> + >>> + return 0; >>> +} >>> + >>> + >>> +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], >>> int num) >>> +{ >>> + int sched = 0; >>> + int i; >>> + odp_buffer_hdr_t *tail; >>> + >>> + for (i = 0; i < num - 1; i++) >>> + buf_hdr[i]->pkt.next = buf_hdr[i+1]; >>> + >>> + tail = buf_hdr[num-1]; >>> + buf_hdr[num-1]->pkt.next = NULL; >>> + >>> + LOCK(&queue->s.lock); >>> + /* Empty queue */ >>> + if (queue->s.head == NULL) >>> + queue->s.head = buf_hdr[0]; >>> + else >>> + queue->s.tail->pkt.next = buf_hdr[0]; >>> + >>> + queue->s.tail = tail; >>> + >>> + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { >>> + queue->s.status = QUEUE_STATUS_SCHED; >>> + sched = 1; /* retval: schedule queue */ >>> + } >>> + UNLOCK(&queue->s.lock); >>> + >>> + /* Add queue to scheduling */ >>> + if (sched == 1) >>> + odp_schedule_queue(queue->s.handle, >>> queue->s.param.sched.prio); >>> + >>> + return 0; >>> +} >>> + >>> + >>> +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int num) >>> +{ >>> + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; >>> + queue_entry_t *queue; >>> + int i; >>> + >>> + if (num > QUEUE_MULTI_MAX) >>> + num = QUEUE_MULTI_MAX; >>> + >>> + queue = queue_to_qentry(handle); >>> + >>> + for (i = 0; i < num; i++) >>> + buf_hdr[i] = odp_buf_to_hdr(buf[i]); >>> + >>> + return queue->s.enqueue_multi(queue, buf_hdr, num); >>> +} >>> + >>> + >>> +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf) >>> +{ >>> + odp_buffer_hdr_t *buf_hdr; >>> + queue_entry_t *queue; >>> + >>> + queue = queue_to_qentry(handle); >>> + buf_hdr = odp_buf_to_hdr(buf); >>> + >>> + return queue->s.enqueue(queue, buf_hdr); >>> +} >>> + >>> + >>> +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue) >>> +{ >>> + odp_buffer_hdr_t *buf_hdr = NULL; >>> + >>> + LOCK(&queue->s.lock); >>> + >>> + if (queue->s.head == NULL) { >>> + /* Already empty queue */ >>> + if (queue->s.status == QUEUE_STATUS_SCHED && >>> + queue->s.type != ODP_QUEUE_TYPE_PKTIN) >>> + queue->s.status = QUEUE_STATUS_NOTSCHED; >>> + } else { >>> + buf_hdr = queue->s.head; >>> + queue->s.head = buf_hdr->pkt.next; >>> + buf_hdr->pkt.next = NULL; >>> + >>> + if (queue->s.head == NULL) { >>> + /* Queue is now empty */ >>> + queue->s.tail = NULL; >>> + } >>> + } >>> + >>> + UNLOCK(&queue->s.lock); >>> + >>> + return buf_hdr; >>> +} >>> + >>> + >>> +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], >>> int num) >>> +{ >>> + int i = 0; >>> + >>> + LOCK(&queue->s.lock); >>> + >>> + if (queue->s.head == NULL) { >>> + /* Already empty queue */ >>> + if (queue->s.status == QUEUE_STATUS_SCHED && >>> + queue->s.type != ODP_QUEUE_TYPE_PKTIN) >>> + queue->s.status = QUEUE_STATUS_NOTSCHED; >>> + } else { >>> + odp_buffer_hdr_t *hdr = queue->s.head; >>> + >>> + for (; i < num && hdr; i++) { >>> + buf_hdr[i] = hdr; >>> + /* odp_prefetch(hdr->addr); */ >>> + hdr = hdr->pkt.next; >>> + buf_hdr[i]->pkt.next = NULL; >>> + } >>> + >>> + queue->s.head = hdr; >>> + >>> + if (hdr == NULL) { >>> + /* Queue is now empty */ >>> + queue->s.tail = NULL; >>> + } >>> + } >>> + >>> + UNLOCK(&queue->s.lock); >>> + >>> + return i; >>> +} >>> + >>> + >>> +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int num) >>> +{ >>> + queue_entry_t *queue; >>> + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; >>> + int i, ret; >>> + >>> + if (num > QUEUE_MULTI_MAX) >>> + num = QUEUE_MULTI_MAX; >>> + >>> + queue = queue_to_qentry(handle); >>> + >>> + ret = queue->s.dequeue_multi(queue, buf_hdr, num); >>> + >>> + for (i = 0; i < ret; i++) >>> + buf[i] = (odp_buffer_t) buf_hdr[i]; >>> + >>> + return ret; >>> +} >>> + >>> + >>> +odp_buffer_t odp_queue_deq(odp_queue_t handle) >>> +{ >>> + queue_entry_t *queue; >>> + odp_buffer_hdr_t *buf_hdr; >>> + >>> + queue = queue_to_qentry(handle); >>> + buf_hdr = queue->s.dequeue(queue); >>> + >>> + if (buf_hdr) >>> + return (odp_buffer_t) buf_hdr; >>> + >>> + return ODP_BUFFER_INVALID; >>> +} >>> + >>> + >>> +void queue_lock(queue_entry_t *queue) >>> +{ >>> + LOCK(&queue->s.lock); >>> +} >>> + >>> + >>> +void queue_unlock(queue_entry_t *queue) >>> +{ >>> + UNLOCK(&queue->s.lock); >>> +} >>> -- >>> 1.9.1 >>> >>> >>> _______________________________________________ >>> lng-odp mailing list >>> lng-odp@lists.linaro.org >>> http://lists.linaro.org/mailman/listinfo/lng-odp >>> >> >> >> >> -- >> *Mike Holmes* >> Linaro Technical Manager / Lead >> LNG - ODP >> > >
On 12 July 2014 17:31, Mike Holmes <mike.holmes@linaro.org> wrote: > > > > On 12 July 2014 04:20, Venkatesh Vivekanandan < > venkatesh.vivekanandan@linaro.org> wrote: > >> >> >> >> On 12 July 2014 01:14, Mike Holmes <mike.holmes@linaro.org> wrote: >> >>> Adds whitespace errors when applied. >>> >> >> Ran checkpatch.pl before submitting the patch. Please point to the >> error/warning if any. >> > mike@fedora1:~/git/odp$ git am > ~/incoming/lng-odp_PATCH_1-2_initial_odp_dpdk.mbox > Applying: initial odp dpdk > error: platform/linux-dpdk/Makefile: already exists in working directory > /home/mike/git/odp/.git/rebase-apply/patch:216: new blank line at EOF. > + > /home/mike/git/odp/.git/rebase-apply/patch:792: new blank line at EOF. > + > /home/mike/git/odp/.git/rebase-apply/patch:988: new blank line at EOF. > + > /home/mike/git/odp/.git/rebase-apply/patch:1134: new blank line at EOF. > + > /home/mike/git/odp/.git/rebase-apply/patch:1192: new blank line at EOF. > + > Patch failed at 0001 initial odp dpdk > The copy of the patch that failed is found in: > /home/mike/git/odp/.git/rebase-apply/patch > When you have resolved this problem, run "git am --continue". > If you prefer to skip this patch, run "git am --skip" instead. > To restore the original branch and stop patching, run "git am --abort". > There are empty lines at end of the file and somehow checkpatch.pl didn't catch, but git am does. I will fix them, add a README and send out a patch v2 > > >> >> >>> Also needs a README like the one in linux-keystone to indicate such >>> things as setting ./configure --with-platform=linux-dpdk >>> And how to then ensure dpdk is installed to resolve things like >>> >> >> Forgot to mention that prerequisite is, dpdk should be checked out and >> compiled. I will probably add it in a README and send out a patch for that. >> >> >>> /usr/include/stdc-predef.h:59:1: fatal error: >>> ../../../dpdk/build/include/rte_config.h: No such file or directory >>> >> >>> >>> On 11 July 2014 14:35, <venkatesh.vivekanandan@linaro.org> wrote: >>> >>>> From: Vincent Hsu <vincent.hsu@linaro.org> >>>> >>>> Signed-off-by: Venkatesh Vivekanandan < >>>> venkatesh.vivekanandan@linaro.org> >>>> --- >>>> platform/linux-dpdk/Makefile | 158 ++++++ >>>> platform/linux-dpdk/Makefile.inc | 7 + >>>> platform/linux-dpdk/include/api/odp_buffer.h | 101 ++++ >>>> platform/linux-dpdk/include/api/odp_buffer_pool.h | 99 ++++ >>>> platform/linux-dpdk/include/api/odp_packet.h | 228 +++++++++ >>>> platform/linux-dpdk/include/api/odp_pktio_types.h | 45 ++ >>>> platform/linux-dpdk/include/odp_buffer_internal.h | 79 +++ >>>> .../linux-dpdk/include/odp_buffer_pool_internal.h | 90 ++++ >>>> platform/linux-dpdk/include/odp_packet_dpdk.h | 88 ++++ >>>> platform/linux-dpdk/include/odp_packet_internal.h | 140 +++++ >>>> .../linux-dpdk/include/odp_packet_io_internal.h | 52 ++ >>>> platform/linux-dpdk/source/odp_buffer.c | 102 ++++ >>>> platform/linux-dpdk/source/odp_buffer_pool.c | 156 ++++++ >>>> platform/linux-dpdk/source/odp_init.c | 113 +++++ >>>> platform/linux-dpdk/source/odp_packet.c | 374 ++++++++++++++ >>>> platform/linux-dpdk/source/odp_packet_dpdk.c | 177 +++++++ >>>> platform/linux-dpdk/source/odp_packet_io.c | 561 >>>> +++++++++++++++++++++ >>>> platform/linux-dpdk/source/odp_queue.c | 435 >>>> ++++++++++++++++ >>>> 18 files changed, 3005 insertions(+) >>>> create mode 100644 platform/linux-dpdk/Makefile >>>> create mode 100644 platform/linux-dpdk/Makefile.inc >>>> create mode 100644 platform/linux-dpdk/include/api/odp_buffer.h >>>> create mode 100644 platform/linux-dpdk/include/api/odp_buffer_pool.h >>>> create mode 100644 platform/linux-dpdk/include/api/odp_packet.h >>>> create mode 100644 platform/linux-dpdk/include/api/odp_pktio_types.h >>>> create mode 100644 platform/linux-dpdk/include/odp_buffer_internal.h >>>> create mode 100644 >>>> platform/linux-dpdk/include/odp_buffer_pool_internal.h >>>> create mode 100644 platform/linux-dpdk/include/odp_packet_dpdk.h >>>> create mode 100644 platform/linux-dpdk/include/odp_packet_internal.h >>>> create mode 100644 platform/linux-dpdk/include/odp_packet_io_internal.h >>>> create mode 100644 platform/linux-dpdk/source/odp_buffer.c >>>> create mode 100644 platform/linux-dpdk/source/odp_buffer_pool.c >>>> create mode 100644 platform/linux-dpdk/source/odp_init.c >>>> create mode 100644 platform/linux-dpdk/source/odp_packet.c >>>> create mode 100644 platform/linux-dpdk/source/odp_packet_dpdk.c >>>> create mode 100644 platform/linux-dpdk/source/odp_packet_io.c >>>> create mode 100644 platform/linux-dpdk/source/odp_queue.c >>>> >>>> diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile >>>> new file mode 100644 >>>> index 0000000..bf8d0b3 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/Makefile >>>> @@ -0,0 +1,158 @@ >>>> +## Copyright (c) 2013, Linaro Limited >>>> +## All rights reserved. >>>> +## >>>> +## Redistribution and use in source and binary forms, with or without >>>> +## modification, are permitted provided that the following conditions >>>> are met: >>>> +## >>>> +## * Redistributions of source code must retain the above copyright >>>> notice, this >>>> +## list of conditions and the following disclaimer. >>>> +## >>>> +## * Redistributions in binary form must reproduce the above >>>> copyright notice, this >>>> +## list of conditions and the following disclaimer in the >>>> documentation and/or >>>> +## other materials provided with the distribution. >>>> +## >>>> +## * Neither the name of Linaro Limited nor the names of its >>>> contributors may be >>>> +## used to endorse or promote products derived from this software >>>> without specific >>>> +## prior written permission. >>>> +## >>>> +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >>>> "AS IS" AND >>>> +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >>>> THE IMPLIED >>>> +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >>>> ARE >>>> +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS >>>> BE LIABLE >>>> +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >>>> CONSEQUENTIAL >>>> +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE >>>> GOODS OR >>>> +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >>>> HOWEVER >>>> +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >>>> LIABILITY, >>>> +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT >>>> OF THE USE >>>> +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >>>> + >>>> +.DEFAULT_GOAL := libs >>>> + >>>> +ODP_ROOT = ../.. >>>> +LIB_DIR = ./lib >>>> +DOC_DIR = ./doc >>>> + >>>> +LINUX_GENERIC_DIR = ../linux-generic >>>> + >>>> +RTE_SDK ?= $(abspath $(ODP_ROOT)/../dpdk) >>>> +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build) >>>> +RTE_LIB ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a) >>>> + >>>> +PLAT_CFLAGS = -include $(RTE_OUTPUT)/include/rte_config.h >>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include >>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch >>>> +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env >>>> +PLAT_CFLAGS += -msse4.2 >>>> + >>>> +EXTRA_CFLAGS += $(PLAT_CFLAGS) >>>> +EXTRA_CFLAGS += -I./include >>>> +EXTRA_CFLAGS += -I./include/api >>>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include >>>> +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api >>>> +EXTRA_CFLAGS += -I$(ODP_ROOT)/include >>>> + >>>> +include $(ODP_ROOT)/Makefile.inc >>>> +STATIC_LIB = ./lib/libodp.a >>>> + >>>> +# >>>> +# Object files >>>> +# >>>> +OBJS = >>>> +OBJS += $(OBJ_DIR)/odp_barrier.o >>>> +OBJS += $(OBJ_DIR)/odp_buffer.o >>>> +OBJS += $(OBJ_DIR)/odp_buffer_pool.o >>>> +OBJS += $(OBJ_DIR)/odp_coremask.o >>>> +OBJS += $(OBJ_DIR)/odp_init.o >>>> +OBJS += $(OBJ_DIR)/odp_linux.o >>>> +OBJS += $(OBJ_DIR)/odp_packet.o >>>> +OBJS += $(OBJ_DIR)/odp_packet_flags.o >>>> +OBJS += $(OBJ_DIR)/odp_packet_io.o >>>> +OBJS += $(OBJ_DIR)/odp_packet_socket.o >>>> +OBJS += $(OBJ_DIR)/odp_queue.o >>>> +OBJS += $(OBJ_DIR)/odp_schedule.o >>>> +OBJS += $(OBJ_DIR)/odp_shared_memory.o >>>> +OBJS += $(OBJ_DIR)/odp_spinlock.o >>>> +OBJS += $(OBJ_DIR)/odp_system_info.o >>>> +OBJS += $(OBJ_DIR)/odp_thread.o >>>> +OBJS += $(OBJ_DIR)/odp_ticketlock.o >>>> +OBJS += $(OBJ_DIR)/odp_time.o >>>> +OBJS += $(OBJ_DIR)/odp_timer.o >>>> +OBJS += $(OBJ_DIR)/odp_ring.o >>>> +OBJS += $(OBJ_DIR)/odp_rwlock.o >>>> +OBJS += $(OBJ_DIR)/odp_packet_dpdk.o >>>> + >>>> +DEPS = $(OBJS:.o=.d) >>>> + >>>> +.PHONY: all >>>> +all: libs docs >>>> + >>>> +-include $(DEPS) >>>> + >>>> +#$(OBJ_DIR): >>>> +# $(MKDIR) $(OBJ_DIR) >>>> + >>>> +$(LIB_DIR): >>>> + $(MKDIR) $(LIB_DIR) >>>> + >>>> +$(DOC_DIR): >>>> + $(MKDIR) $(DOC_DIR)/html >>>> + $(MKDIR) $(DOC_DIR)/latex >>>> + >>>> +# >>>> +# Compile rules >>>> +# >>>> +vpath %.c source:$(LINUX_GENERIC_DIR)/source >>>> + >>>> +$(OBJ_DIR)/%.o: %.c >>>> + $(ECHO) " CC $<" >>>> + $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $< >>>> + >>>> +# >>>> +# Lib rule >>>> +# >>>> +$(OBJ_DIR)/libodp.o: $(OBJS) >>>> + $(ECHO) " LD $@" >>>> + $(LD) -r -o $@ $(OBJS) $(RTE_LIB) >>>> + >>>> +$(STATIC_LIB): $(OBJ_DIR)/libodp.o >>>> + $(ECHO) " AR $@" >>>> + $(AR) -cr $@ $(OBJ_DIR)/libodp.o >>>> + >>>> + >>>> +clean: >>>> + $(RMDIR) $(OBJ_DIR) >>>> + $(RMDIR) $(LIB_DIR) >>>> + $(RMDIR) $(DOC_DIR) >>>> + $(RM) Doxyfile >>>> + >>>> +Doxyfile: Doxyfile.in >>>> + doxygen -u - < $< > $@ >>>> + >>>> +.PHONY: docs >>>> +docs: $(DOC_DIR) Doxyfile ./include/odp*.h >>>> + doxygen >>>> + >>>> +.PHONY: docs_install >>>> +docs_install: docs >>>> + $(COPY) doc $(DESTDIR) >>>> + >>>> +.PHONY: pdf >>>> +pdf: docs >>>> + make --directory doc/latex refman.pdf 1> /dev/null >>>> + >>>> +.PHONY: libs >>>> +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB) >>>> + >>>> +.PHONY: lib_install >>>> +lib_install: libs >>>> + install -d $(DESTDIR)/lib >>>> + install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/ >>>> + >>>> +.PHONY: headers_install >>>> +headers_install: libs >>>> + $(ECHO) Installing headers to $(DESTDIR)/include >>>> + $(COPY) $(ODP_ROOT)/include $(DESTDIR) >>>> + $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/ >>>> + $(COPY) include/api/* $(DESTDIR)/include/ >>>> + >>>> +install: lib_install headers_install >>>> diff --git a/platform/linux-dpdk/Makefile.inc >>>> b/platform/linux-dpdk/Makefile.inc >>>> new file mode 100644 >>>> index 0000000..fe7679b >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/Makefile.inc >>>> @@ -0,0 +1,7 @@ >>>> +# Copyright (c) 2013, Linaro Limited >>>> +# All rights reserved. >>>> +# >>>> +# SPDX-License-Identifier: BSD-3-Clause >>>> + >>>> +STD_LIBS += -ldl >>>> + >>>> diff --git a/platform/linux-dpdk/include/api/odp_buffer.h >>>> b/platform/linux-dpdk/include/api/odp_buffer.h >>>> new file mode 100644 >>>> index 0000000..286d9e6 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/api/odp_buffer.h >>>> @@ -0,0 +1,101 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> + >>>> +/** >>>> + * @file >>>> + * >>>> + * ODP buffer descriptor >>>> + */ >>>> + >>>> +#ifndef ODP_BUFFER_H_ >>>> +#define ODP_BUFFER_H_ >>>> + >>>> +#ifdef __cplusplus >>>> +extern "C" { >>>> +#endif >>>> + >>>> + >>>> + >>>> +#include <odp_std_types.h> >>>> + >>>> + >>>> + >>>> + >>>> + >>>> +/** >>>> + * ODP buffer >>>> + */ >>>> +typedef unsigned long odp_buffer_t; >>>> + >>>> + >>>> +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */ >>>> + >>>> + >>>> +/** >>>> + * Buffer start address >>>> + * >>>> + * @param buf Buffer handle >>>> + * >>>> + * @return Buffer start address >>>> + */ >>>> +void *odp_buffer_addr(odp_buffer_t buf); >>>> + >>>> +/** >>>> + * Buffer maximum data size >>>> + * >>>> + * @param buf Buffer handle >>>> + * >>>> + * @return Buffer maximum data size >>>> + */ >>>> +size_t odp_buffer_size(odp_buffer_t buf); >>>> + >>>> +/** >>>> + * Buffer type >>>> + * >>>> + * @param buf Buffer handle >>>> + * >>>> + * @return Buffer type >>>> + */ >>>> +int odp_buffer_type(odp_buffer_t buf); >>>> + >>>> +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */ >>>> +#define ODP_BUFFER_TYPE_RAW 0 /**< Raw buffer */ >>>> +#define ODP_BUFFER_TYPE_PACKET 1 /**< Packet buffer */ >>>> +#define ODP_BUFFER_TYPE_TIMER 2 /**< Timer buffer */ >>>> + >>>> +/** >>>> + * Tests if buffer is part of a scatter/gather list >>>> + * >>>> + * @param buf Buffer handle >>>> + * >>>> + * @return 1 if belongs to a scatter list, otherwise 0 >>>> + */ >>>> +int odp_buffer_is_scatter(odp_buffer_t buf); >>>> + >>>> +/** >>>> + * Tests if buffer is valid >>>> + * >>>> + * @param buf Buffer handle >>>> + * >>>> + * @return 1 if valid, otherwise 0 >>>> + */ >>>> +int odp_buffer_is_valid(odp_buffer_t buf); >>>> + >>>> +/** >>>> + * Print buffer metadata to STDOUT >>>> + * >>>> + * @param buf Buffer handle >>>> + * >>>> + */ >>>> +void odp_buffer_print(odp_buffer_t buf); >>>> + >>>> + >>>> +#ifdef __cplusplus >>>> +} >>>> +#endif >>>> + >>>> +#endif >>>> diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h >>>> b/platform/linux-dpdk/include/api/odp_buffer_pool.h >>>> new file mode 100644 >>>> index 0000000..4b75cf5 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h >>>> @@ -0,0 +1,99 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> + >>>> +/** >>>> + * @file >>>> + * >>>> + * ODP buffer pool >>>> + */ >>>> + >>>> +#ifndef ODP_BUFFER_POOL_H_ >>>> +#define ODP_BUFFER_POOL_H_ >>>> + >>>> +#ifdef __cplusplus >>>> +extern "C" { >>>> +#endif >>>> + >>>> + >>>> + >>>> +#include <odp_std_types.h> >>>> +#include <odp_buffer.h> >>>> + >>>> +/** Maximum queue name lenght in chars */ >>>> +#define ODP_BUFFER_POOL_NAME_LEN 32 >>>> + >>>> +/** Invalid buffer pool */ >>>> +#define ODP_BUFFER_POOL_INVALID (0xffffffff) >>>> + >>>> +/** ODP buffer pool */ >>>> +typedef unsigned long odp_buffer_pool_t; >>>> + >>>> + >>>> +/** >>>> + * Create a buffer pool >>>> + * >>>> + * @param name Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1 >>>> chars) >>>> + * @param base_addr Pool base address >>>> + * @param size Pool size in bytes >>>> + * @param buf_size Buffer size in bytes >>>> + * @param buf_align Minimum buffer alignment >>>> + * @param buf_type Buffer type >>>> + * >>>> + * @return Buffer pool handle >>>> + */ >>>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name, >>>> + void *base_addr, uint64_t size, >>>> + size_t buf_size, size_t >>>> buf_align, >>>> + int buf_type); >>>> + >>>> + >>>> +/** >>>> + * Find a buffer pool by name >>>> + * >>>> + * @param name Name of the pool >>>> + * >>>> + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found. >>>> + */ >>>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name); >>>> + >>>> + >>>> +/** >>>> + * Print buffer pool info >>>> + * >>>> + * @param pool Pool handle >>>> + * >>>> + */ >>>> +void odp_buffer_pool_print(odp_buffer_pool_t pool); >>>> + >>>> + >>>> + >>>> +/** >>>> + * Buffer alloc >>>> + * >>>> + * @param pool Pool handle >>>> + * >>>> + * @return Buffer handle or ODP_BUFFER_INVALID >>>> + */ >>>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool); >>>> + >>>> + >>>> +/** >>>> + * Buffer free >>>> + * >>>> + * @param buf Buffer handle >>>> + * >>>> + */ >>>> +void odp_buffer_free(odp_buffer_t buf); >>>> + >>>> + >>>> + >>>> + >>>> +#ifdef __cplusplus >>>> +} >>>> +#endif >>>> + >>>> +#endif >>>> diff --git a/platform/linux-dpdk/include/api/odp_packet.h >>>> b/platform/linux-dpdk/include/api/odp_packet.h >>>> new file mode 100644 >>>> index 0000000..bdb3417 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/api/odp_packet.h >>>> @@ -0,0 +1,228 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> + >>>> +/** >>>> + * @file >>>> + * >>>> + * ODP packet descriptor >>>> + */ >>>> + >>>> +#ifndef ODP_PACKET_H_ >>>> +#define ODP_PACKET_H_ >>>> + >>>> +#ifdef __cplusplus >>>> +extern "C" { >>>> +#endif >>>> + >>>> +#include <odp_buffer.h> >>>> + >>>> + >>>> +/** >>>> + * ODP packet descriptor >>>> + */ >>>> +typedef unsigned long odp_packet_t; >>>> + >>>> + >>>> +/** Invalid packet */ >>>> +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID >>>> + >>>> +/** Invalid offset */ >>>> +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1) >>>> + >>>> + >>>> +/** >>>> + * Initialize the packet >>>> + * >>>> + * Needs to be called if the user allocates a packet buffer, i.e. the >>>> packet >>>> + * has not been received from I/O through ODP. >>>> + * >>>> + * @param pkt Packet handle >>>> + */ >>>> +void odp_packet_init(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Convert from packet handle to buffer handle >>>> + * >>>> + * @param buf Buffer handle >>>> + * >>>> + * @return Packet handle >>>> + */ >>>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf); >>>> + >>>> +/** >>>> + * Convert from buffer handle to packet handle >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return Buffer handle >>>> + */ >>>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Set the packet length >>>> + * >>>> + * @param pkt Packet handle >>>> + * @param len Length of packet in bytes >>>> + */ >>>> +void odp_packet_set_len(odp_packet_t pkt, size_t len); >>>> + >>>> +/** >>>> + * Get the packet length >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return Packet length in bytes >>>> + */ >>>> +size_t odp_packet_get_len(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Get address to the start of the packet buffer >>>> + * >>>> + * The address of the packet buffer is not necessarily the same as the >>>> start >>>> + * address of the received frame, e.g. an eth frame may be offset by 2 >>>> or 6 >>>> + * bytes to ensure 32 or 64-bit alignment of the IP header. >>>> + * Use odp_packet_l2(pkt) to get the start address of a received valid >>>> frame >>>> + * or odp_packet_start(pkt) to get the start address even if no valid >>>> L2 header >>>> + * could be found. >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return Pointer to the start of the packet buffer >>>> + * >>>> + * @see odp_packet_l2(), odp_packet_start() >>>> + */ >>>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Get pointer to the start of the received frame >>>> + * >>>> + * The address of the packet buffer is not necessarily the same as the >>>> start >>>> + * address of the received frame, e.g. an eth frame may be offset by 2 >>>> or 6 >>>> + * bytes to ensure 32 or 64-bit alignment of the IP header. >>>> + * Use odp_packet_l2(pkt) to get the start address of a received valid >>>> eth frame >>>> + * >>>> + * odp_packet_start() will always return a pointer to the start of the >>>> frame, >>>> + * even if the frame is unrecognized and no valid L2 header could be >>>> found. >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return Pointer to the start of the received frame >>>> + * >>>> + * @see odp_packet_l2(), odp_packet_buf_addr() >>>> + */ >>>> +uint8_t *odp_packet_start(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Get pointer to the start of the L2 frame >>>> + * >>>> + * The L2 frame header address is not necessarily the same as the >>>> address of the >>>> + * packet buffer, see odp_packet_buf_addr() >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return Pointer to L2 header or NULL if not found >>>> + * >>>> + * @see odp_packet_buf_addr(), odp_packet_start() >>>> + */ >>>> +uint8_t *odp_packet_l2(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Return the byte offset from the packet buffer to the L2 frame >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found >>>> + */ >>>> +size_t odp_packet_l2_offset(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Set the byte offset to the L2 frame >>>> + * >>>> + * @param pkt Packet handle >>>> + * @param offset L2 byte offset >>>> + */ >>>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset); >>>> + >>>> + >>>> +/** >>>> + * Get pointer to the start of the L3 packet >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return Pointer to L3 packet or NULL if not found >>>> + * >>>> + */ >>>> +uint8_t *odp_packet_l3(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Return the byte offset from the packet buffer to the L3 packet >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found >>>> + */ >>>> +size_t odp_packet_l3_offset(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Set the byte offset to the L3 packet >>>> + * >>>> + * @param pkt Packet handle >>>> + * @param offset L3 byte offset >>>> + */ >>>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset); >>>> + >>>> + >>>> +/** >>>> + * Get pointer to the start of the L4 packet >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return Pointer to L4 packet or NULL if not found >>>> + * >>>> + */ >>>> +uint8_t *odp_packet_l4(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Return the byte offset from the packet buffer to the L4 packet >>>> + * >>>> + * @param pkt Packet handle >>>> + * >>>> + * @return L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found >>>> + */ >>>> +size_t odp_packet_l4_offset(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Set the byte offset to the L4 packet >>>> + * >>>> + * @param pkt Packet handle >>>> + * @param offset L4 byte offset >>>> + */ >>>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset); >>>> + >>>> +/** >>>> + * Print (debug) information about the packet >>>> + * >>>> + * @param pkt Packet handle >>>> + */ >>>> +void odp_packet_print(odp_packet_t pkt); >>>> + >>>> +/** >>>> + * Copy contents and metadata from pkt_src to pkt_dst >>>> + * Useful when creating copies of packets >>>> + * >>>> + * @param pkt_dst Destination packet >>>> + * @param pkt_src Source packet >>>> + * >>>> + * @return 0 if successful >>>> + */ >>>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src); >>>> + >>>> +#ifdef __cplusplus >>>> +} >>>> +#endif >>>> + >>>> +#endif >>>> diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h >>>> b/platform/linux-dpdk/include/api/odp_pktio_types.h >>>> new file mode 100644 >>>> index 0000000..b23e6da >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h >>>> @@ -0,0 +1,45 @@ >>>> + >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#ifndef ODP_PKTIO_TYPES_H >>>> +#define ODP_PKTIO_TYPES_H >>>> + >>>> +#ifdef __cplusplus >>>> +extern "C" { >>>> +#endif >>>> + >>>> +/* We should ensure that future enum values will never overlap, >>>> otherwise >>>> + * applications that want netmap suport might get in trouble if the >>>> odp lib >>>> + * was not built with netmap support and there are more types define >>>> below >>>> + */ >>>> + >>>> +typedef enum { >>>> + ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1, >>>> + ODP_PKTIO_TYPE_SOCKET_MMSG, >>>> + ODP_PKTIO_TYPE_SOCKET_MMAP, >>>> + ODP_PKTIO_TYPE_NETMAP, >>>> + ODP_PKTIO_TYPE_DPDK, >>>> +} odp_pktio_type_t; >>>> + >>>> +#include <odp_pktio_socket.h> >>>> +#ifdef ODP_HAVE_NETMAP >>>> +#include <odp_pktio_netmap.h> >>>> +#endif >>>> + >>>> +typedef union odp_pktio_params_t { >>>> + odp_pktio_type_t type; >>>> + socket_params_t sock_params; >>>> +#ifdef ODP_HAVE_NETMAP >>>> + netmap_params_t nm_params; >>>> +#endif >>>> +} odp_pktio_params_t; >>>> + >>>> +#ifdef __cplusplus >>>> +} >>>> +#endif >>>> + >>>> +#endif >>>> diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h >>>> b/platform/linux-dpdk/include/odp_buffer_internal.h >>>> new file mode 100644 >>>> index 0000000..a47107c >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/odp_buffer_internal.h >>>> @@ -0,0 +1,79 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> + >>>> +/** >>>> + * @file >>>> + * >>>> + * ODP buffer descriptor - implementation internal >>>> + */ >>>> + >>>> +#ifndef ODP_BUFFER_INTERNAL_H_ >>>> +#define ODP_BUFFER_INTERNAL_H_ >>>> + >>>> +#ifdef __cplusplus >>>> +extern "C" { >>>> +#endif >>>> + >>>> +#include <odp_std_types.h> >>>> +#include <odp_atomic.h> >>>> +#include <odp_buffer_pool.h> >>>> +#include <odp_buffer.h> >>>> +#include <odp_debug.h> >>>> +#include <odp_align.h> >>>> +#include <rte_mbuf.h> >>>> + >>>> +/* TODO: move these to correct files */ >>>> + >>>> +typedef uint64_t odp_phys_addr_t; >>>> + >>>> +#define ODP_BUFFER_MAX_INDEX (ODP_BUFFER_MAX_BUFFERS - 2) >>>> +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1) >>>> + >>>> +#define ODP_BUFS_PER_CHUNK 16 >>>> +#define ODP_BUFS_PER_SCATTER 4 >>>> + >>>> +#define ODP_BUFFER_TYPE_CHUNK 0xffff >>>> + >>>> + >>>> +#define ODP_BUFFER_POOL_BITS 4 >>>> +#define ODP_BUFFER_INDEX_BITS (32 - ODP_BUFFER_POOL_BITS) >>>> +#define ODP_BUFFER_MAX_POOLS (1 << ODP_BUFFER_POOL_BITS) >>>> +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS) >>>> + >>>> +typedef union odp_buffer_bits_t { >>>> + uint32_t u32; >>>> + odp_buffer_t handle; >>>> + >>>> + struct { >>>> + uint32_t pool:ODP_BUFFER_POOL_BITS; >>>> + uint32_t index:ODP_BUFFER_INDEX_BITS; >>>> + }; >>>> +} odp_buffer_bits_t; >>>> + >>>> + >>>> +/* forward declaration */ >>>> +struct odp_buffer_hdr_t; >>>> + >>>> + >>>> +typedef struct rte_mbuf odp_buffer_hdr_t; >>>> + >>>> + >>>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf); >>>> + >>>> + >>>> +#ifdef __cplusplus >>>> +} >>>> +#endif >>>> + >>>> +#endif >>>> + >>>> + >>>> + >>>> + >>>> + >>>> + >>>> + >>>> diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h >>>> b/platform/linux-dpdk/include/odp_buffer_pool_internal.h >>>> new file mode 100644 >>>> index 0000000..1a36655 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h >>>> @@ -0,0 +1,90 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> + >>>> +/** >>>> + * @file >>>> + * >>>> + * ODP buffer pool - internal header >>>> + */ >>>> + >>>> +#ifndef ODP_BUFFER_POOL_INTERNAL_H_ >>>> +#define ODP_BUFFER_POOL_INTERNAL_H_ >>>> + >>>> +#ifdef __cplusplus >>>> +extern "C" { >>>> +#endif >>>> + >>>> +#include <odp_std_types.h> >>>> +#include <odp_buffer_pool.h> >>>> +#include <odp_buffer_internal.h> >>>> +#include <odp_align.h> >>>> +#include <odp_hints.h> >>>> +#include <odp_config.h> >>>> +#include <odp_debug.h> >>>> + >>>> +/* for DPDK */ >>>> +#include <rte_mempool.h> >>>> + >>>> +/* Use ticketlock instead of spinlock */ >>>> +#define POOL_USE_TICKETLOCK >>>> + >>>> +/* Extra error checks */ >>>> +/* #define POOL_ERROR_CHECK */ >>>> + >>>> + >>>> +#ifdef POOL_USE_TICKETLOCK >>>> +#include <odp_ticketlock.h> >>>> +#else >>>> +#include <odp_spinlock.h> >>>> +#endif >>>> + >>>> + >>>> +struct pool_entry_s { >>>> +#ifdef POOL_USE_TICKETLOCK >>>> + odp_ticketlock_t lock ODP_ALIGNED_CACHE; >>>> +#else >>>> + odp_spinlock_t lock ODP_ALIGNED_CACHE; >>>> +#endif >>>> + >>>> + uint64_t free_bufs; >>>> + char name[ODP_BUFFER_POOL_NAME_LEN]; >>>> + >>>> + >>>> + odp_buffer_pool_t pool ODP_ALIGNED_CACHE; >>>> + uintptr_t buf_base; >>>> + size_t buf_size; >>>> + size_t buf_offset; >>>> + uint64_t num_bufs; >>>> + void *pool_base_addr; >>>> + uint64_t pool_size; >>>> + size_t payload_size; >>>> + size_t payload_align; >>>> + int buf_type; >>>> + size_t hdr_size; >>>> +}; >>>> + >>>> + >>>> +extern void *pool_entry_ptr[]; >>>> + >>>> + >>>> +static inline void *get_pool_entry(odp_buffer_pool_t pool_id) >>>> +{ >>>> + return pool_entry_ptr[pool_id]; >>>> +} >>>> + >>>> + >>>> +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf) >>>> +{ >>>> + return (odp_buffer_hdr_t *)buf; >>>> +} >>>> + >>>> + >>>> +#ifdef __cplusplus >>>> +} >>>> +#endif >>>> + >>>> +#endif >>>> diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h >>>> b/platform/linux-dpdk/include/odp_packet_dpdk.h >>>> new file mode 100644 >>>> index 0000000..0b3db08 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h >>>> @@ -0,0 +1,88 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#ifndef ODP_PACKET_DPDK_H >>>> +#define ODP_PACKET_DPDK_H >>>> + >>>> +#include <stdint.h> >>>> +#include <net/if.h> >>>> + >>>> +#include <helper/odp_eth.h> >>>> +#include <helper/odp_packet_helper.h> >>>> +#include <odp_align.h> >>>> +#include <odp_debug.h> >>>> +#include <odp_packet.h> >>>> +#include <odp_packet_internal.h> >>>> +#include <odp_buffer_pool.h> >>>> +#include <odp_buffer_pool_internal.h> >>>> +#include <odp_buffer_internal.h> >>>> +#include <odp_std_types.h> >>>> + >>>> +#include <rte_config.h> >>>> +#include <rte_memory.h> >>>> +#include <rte_memzone.h> >>>> +#include <rte_launch.h> >>>> +#include <rte_tailq.h> >>>> +#include <rte_eal.h> >>>> +#include <rte_per_lcore.h> >>>> +#include <rte_lcore.h> >>>> +#include <rte_branch_prediction.h> >>>> +#include <rte_prefetch.h> >>>> +#include <rte_cycles.h> >>>> +#include <rte_errno.h> >>>> +#include <rte_debug.h> >>>> +#include <rte_log.h> >>>> +#include <rte_byteorder.h> >>>> +#include <rte_pci.h> >>>> +#include <rte_random.h> >>>> +#include <rte_ether.h> >>>> +#include <rte_ethdev.h> >>>> +#include <rte_hash.h> >>>> +#include <rte_jhash.h> >>>> +#include <rte_hash_crc.h> >>>> + >>>> + >>>> +#define ODP_DPDK_MODE_HW 0 >>>> +#define ODP_DPDK_MODE_SW 1 >>>> + >>>> +#define DPDK_BLOCKING_IO >>>> + >>>> +/** Packet socket using dpdk mmaped rings for both Rx and Tx */ >>>> +typedef struct { >>>> + odp_buffer_pool_t pool; >>>> + >>>> + /********************************/ >>>> + char ifname[32]; >>>> + uint8_t portid; >>>> + uint16_t queueid; >>>> +} pkt_dpdk_t; >>>> + >>>> +/** >>>> + * Configure an interface to work in dpdk mode >>>> + */ >>>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, >>>> + odp_buffer_pool_t pool); >>>> + >>>> +/** >>>> + * Switch interface from dpdk mode to normal mode >>>> + */ >>>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk); >>>> + >>>> +/** >>>> + * Receive packets using dpdk >>>> + */ >>>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t >>>> pkt_table[], >>>> + unsigned len); >>>> + >>>> +/** >>>> + * Send packets using dpdk >>>> + */ >>>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t >>>> pkt_table[], >>>> + unsigned len); >>>> + >>>> +int odp_init_dpdk(void); >>>> +#endif >>>> + >>>> diff --git a/platform/linux-dpdk/include/odp_packet_internal.h >>>> b/platform/linux-dpdk/include/odp_packet_internal.h >>>> new file mode 100644 >>>> index 0000000..d9057a2 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/odp_packet_internal.h >>>> @@ -0,0 +1,140 @@ >>>> +/* Copyright (c) 2014, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> + >>>> +/** >>>> + * @file >>>> + * >>>> + * ODP packet descriptor - implementation internal >>>> + */ >>>> + >>>> +#ifndef ODP_PACKET_INTERNAL_H_ >>>> +#define ODP_PACKET_INTERNAL_H_ >>>> + >>>> +#ifdef __cplusplus >>>> +extern "C" { >>>> +#endif >>>> + >>>> +#include <odp_align.h> >>>> +#include <odp_debug.h> >>>> +#include <odp_buffer_internal.h> >>>> +#include <odp_buffer_pool_internal.h> >>>> +#include <odp_packet.h> >>>> +#include <odp_packet_io.h> >>>> + >>>> +/** >>>> + * Packet input & protocol flags >>>> + */ >>>> +typedef union { >>>> + /* All input flags */ >>>> + uint32_t all; >>>> + >>>> + struct { >>>> + /* Bitfield flags for each protocol */ >>>> + uint32_t l2:1; /**< known L2 protocol present */ >>>> + uint32_t l3:1; /**< known L3 protocol present */ >>>> + uint32_t l4:1; /**< known L4 protocol present */ >>>> + >>>> + uint32_t eth:1; /**< Ethernet */ >>>> + uint32_t jumbo:1; /**< Jumbo frame */ >>>> + uint32_t vlan:1; /**< VLAN hdr found */ >>>> + uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */ >>>> + >>>> + uint32_t arp:1; /**< ARP */ >>>> + >>>> + uint32_t ipv4:1; /**< IPv4 */ >>>> + uint32_t ipv6:1; /**< IPv6 */ >>>> + uint32_t ipfrag:1; /**< IP fragment */ >>>> + uint32_t ipopt:1; /**< IP optional headers */ >>>> + uint32_t ipsec:1; /**< IPSec decryption may be >>>> needed */ >>>> + >>>> + uint32_t udp:1; /**< UDP */ >>>> + uint32_t tcp:1; /**< TCP */ >>>> + uint32_t sctp:1; /**< SCTP */ >>>> + uint32_t icmp:1; /**< ICMP */ >>>> + }; >>>> +} input_flags_t; >>>> + >>>> +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t), >>>> INPUT_FLAGS_SIZE_ERROR); >>>> + >>>> +/** >>>> + * Packet error flags >>>> + */ >>>> +typedef union { >>>> + /* All error flags */ >>>> + uint32_t all; >>>> + >>>> + struct { >>>> + /* Bitfield flags for each detected error */ >>>> + uint32_t frame_len:1; /**< Frame length error */ >>>> + uint32_t l2_chksum:1; /**< L2 checksum error, checks >>>> TBD */ >>>> + uint32_t ip_err:1; /**< IP error, checks TBD */ >>>> + uint32_t tcp_err:1; /**< TCP error, checks TBD */ >>>> + uint32_t udp_err:1; /**< UDP error, checks TBD */ >>>> + }; >>>> +} error_flags_t; >>>> + >>>> +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t), >>>> ERROR_FLAGS_SIZE_ERROR); >>>> + >>>> +/** >>>> + * Packet output flags >>>> + */ >>>> +typedef union { >>>> + /* All output flags */ >>>> + uint32_t all; >>>> + >>>> + struct { >>>> + /* Bitfield flags for each output option */ >>>> + uint32_t l4_chksum:1; /**< Request L4 checksum >>>> calculation */ >>>> + }; >>>> +} output_flags_t; >>>> + >>>> +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), >>>> OUTPUT_FLAGS_SIZE_ERROR); >>>> + >>>> +/** >>>> + * Internal Packet header >>>> + */ >>>> +typedef struct { >>>> + /* common buffer header */ >>>> + odp_buffer_hdr_t buf_hdr; >>>> + >>>> + input_flags_t input_flags; >>>> + error_flags_t error_flags; >>>> + output_flags_t output_flags; >>>> + >>>> + uint32_t frame_offset; /**< offset to start of frame, even on >>>> error */ >>>> + uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */ >>>> + uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */ >>>> + uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also >>>> ICMP) */ >>>> + >>>> + uint32_t frame_len; >>>> + >>>> + odp_pktio_t input; >>>> + >>>> + uint32_t pad; >>>> + uint8_t payload[]; >>>> + >>>> +} odp_packet_hdr_t; >>>> + >>>> +/** >>>> + * Return the packet header >>>> + */ >>>> +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt) >>>> +{ >>>> + return (odp_packet_hdr_t *)pkt; >>>> +} >>>> + >>>> +/** >>>> + * Parse packet and set internal metadata >>>> + */ >>>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset); >>>> + >>>> +#ifdef __cplusplus >>>> +} >>>> +#endif >>>> + >>>> +#endif >>>> + >>>> diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h >>>> b/platform/linux-dpdk/include/odp_packet_io_internal.h >>>> new file mode 100644 >>>> index 0000000..5948063 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h >>>> @@ -0,0 +1,52 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> + >>>> +/** >>>> + * @file >>>> + * >>>> + * ODP packet IO - implementation internal >>>> + */ >>>> + >>>> +#ifndef ODP_PACKET_IO_INTERNAL_H_ >>>> +#define ODP_PACKET_IO_INTERNAL_H_ >>>> + >>>> +#ifdef __cplusplus >>>> +extern "C" { >>>> +#endif >>>> + >>>> +#include <odp_spinlock.h> >>>> +#include <odp_packet_socket.h> >>>> +#ifdef ODP_HAVE_NETMAP >>>> +#include <odp_packet_netmap.h> >>>> +#endif >>>> +#include <odp_packet_dpdk.h> >>>> + >>>> +struct pktio_entry { >>>> + odp_spinlock_t lock; /**< entry spinlock */ >>>> + int taken; /**< is entry taken(1) or >>>> free(0) */ >>>> + odp_queue_t inq_default; /**< default input queue, if >>>> set */ >>>> + odp_queue_t outq_default; /**< default out queue */ >>>> + odp_pktio_params_t params; /**< pktio parameters */ >>>> + pkt_sock_t pkt_sock; /**< using socket API for IO */ >>>> + pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap API for >>>> IO */ >>>> +#ifdef ODP_HAVE_NETMAP >>>> + pkt_netmap_t pkt_nm; /**< using netmap API for IO */ >>>> +#endif >>>> + pkt_dpdk_t pkt_dpdk; /**< using DPDK API for IO */ >>>> +}; >>>> + >>>> +typedef union { >>>> + struct pktio_entry s; >>>> + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct >>>> pktio_entry))]; >>>> +} pktio_entry_t; >>>> + >>>> +#ifdef __cplusplus >>>> +} >>>> +#endif >>>> + >>>> +#endif >>>> + >>>> diff --git a/platform/linux-dpdk/source/odp_buffer.c >>>> b/platform/linux-dpdk/source/odp_buffer.c >>>> new file mode 100644 >>>> index 0000000..bfb5ff6 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/source/odp_buffer.c >>>> @@ -0,0 +1,102 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#include <odp_buffer.h> >>>> +#include <odp_buffer_internal.h> >>>> +#include <odp_buffer_pool_internal.h> >>>> + >>>> +#include <string.h> >>>> +#include <stdio.h> >>>> + >>>> + >>>> +void *odp_buffer_addr(odp_buffer_t buf) >>>> +{ >>>> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >>>> + >>>> + return hdr->buf_addr; >>>> +} >>>> + >>>> + >>>> +size_t odp_buffer_size(odp_buffer_t buf) >>>> +{ >>>> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >>>> + >>>> + return hdr->buf_len; >>>> +} >>>> + >>>> + >>>> +int odp_buffer_type(odp_buffer_t buf) >>>> +{ >>>> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >>>> + >>>> + return hdr->type; >>>> +} >>>> + >>>> + >>>> +int odp_buffer_is_scatter(odp_buffer_t buf) >>>> +{ >>>> + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); >>>> + >>>> + if (hdr->refcnt == 0) >>>> + return 0; >>>> + else >>>> + return 1; >>>> +} >>>> + >>>> + >>>> +int odp_buffer_is_valid(odp_buffer_t buf) >>>> +{ >>>> + odp_buffer_bits_t handle; >>>> + >>>> + handle.u32 = buf; >>>> + >>>> + return (handle.index != ODP_BUFFER_INVALID_INDEX); >>>> +} >>>> + >>>> + >>>> +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf) >>>> +{ >>>> + odp_buffer_hdr_t *hdr; >>>> + int len = 0; >>>> + >>>> + if (!odp_buffer_is_valid(buf)) { >>>> + printf("Buffer is not valid.\n"); >>>> + return len; >>>> + } >>>> + >>>> + hdr = odp_buf_to_hdr(buf); >>>> + >>>> + len += snprintf(&str[len], n-len, >>>> + "Buffer\n"); >>>> + len += snprintf(&str[len], n-len, >>>> + " pool %"PRIu64"\n", (int64_t) >>>> hdr->pool); >>>> + len += snprintf(&str[len], n-len, >>>> + " phy_addr %"PRIu64"\n", >>>> hdr->buf_physaddr); >>>> + len += snprintf(&str[len], n-len, >>>> + " addr %p\n", hdr->buf_addr); >>>> + len += snprintf(&str[len], n-len, >>>> + " size %u\n", hdr->buf_len); >>>> + len += snprintf(&str[len], n-len, >>>> + " ref_count %i\n", hdr->refcnt); >>>> + len += snprintf(&str[len], n-len, >>>> + " type %i\n", hdr->type); >>>> + >>>> + return len; >>>> +} >>>> + >>>> + >>>> +void odp_buffer_print(odp_buffer_t buf) >>>> +{ >>>> + int max_len = 512; >>>> + char str[max_len]; >>>> + int len; >>>> + >>>> + len = odp_buffer_snprint(str, max_len-1, buf); >>>> + str[len] = 0; >>>> + >>>> + printf("\n%s\n", str); >>>> +} >>>> + >>>> diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c >>>> b/platform/linux-dpdk/source/odp_buffer_pool.c >>>> new file mode 100644 >>>> index 0000000..de90275 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/source/odp_buffer_pool.c >>>> @@ -0,0 +1,156 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#include <odp_std_types.h> >>>> +#include <odp_buffer_pool.h> >>>> +#include <odp_buffer_pool_internal.h> >>>> +#include <odp_buffer_internal.h> >>>> +#include <odp_packet_internal.h> >>>> +#include <odp_shared_memory.h> >>>> +#include <odp_align.h> >>>> +#include <odp_internal.h> >>>> +#include <odp_config.h> >>>> +#include <odp_hints.h> >>>> +#include <odp_debug.h> >>>> + >>>> +#include <string.h> >>>> +#include <stdlib.h> >>>> + >>>> +/* for DPDK */ >>>> +#include <odp_packet_dpdk.h> >>>> + >>>> +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + >>>> RTE_PKTMBUF_HEADROOM) >>>> +#define NB_MBUF 8192 >>>> + >>>> +#ifdef POOL_USE_TICKETLOCK >>>> +#include <odp_ticketlock.h> >>>> +#define LOCK(a) odp_ticketlock_lock(a) >>>> +#define UNLOCK(a) odp_ticketlock_unlock(a) >>>> +#define LOCK_INIT(a) odp_ticketlock_init(a) >>>> +#else >>>> +#include <odp_spinlock.h> >>>> +#define LOCK(a) odp_spinlock_lock(a) >>>> +#define UNLOCK(a) odp_spinlock_unlock(a) >>>> +#define LOCK_INIT(a) odp_spinlock_init(a) >>>> +#endif >>>> + >>>> + >>>> +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS >>>> +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS >>>> +#endif >>>> + >>>> +#define NULL_INDEX ((uint32_t)-1) >>>> + >>>> + >>>> +typedef union pool_entry_u { >>>> + struct pool_entry_s s; >>>> + >>>> + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct >>>> pool_entry_s))]; >>>> + >>>> +} pool_entry_t; >>>> + >>>> + >>>> +typedef struct pool_table_t { >>>> + pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS]; >>>> + >>>> +} pool_table_t; >>>> + >>>> + >>>> +/* The pool table */ >>>> +static pool_table_t *pool_tbl; >>>> + >>>> +/* Pool entry pointers (for inlining) */ >>>> +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS]; >>>> + >>>> + >>>> +int odp_buffer_pool_init_global(void) >>>> +{ >>>> + odp_buffer_pool_t i; >>>> + >>>> + pool_tbl = odp_shm_reserve("odp_buffer_pools", >>>> + sizeof(pool_table_t), >>>> + sizeof(pool_entry_t)); >>>> + >>>> + if (pool_tbl == NULL) >>>> + return -1; >>>> + >>>> + memset(pool_tbl, 0, sizeof(pool_table_t)); >>>> + >>>> + >>>> + for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) { >>>> + /* init locks */ >>>> + pool_entry_t *pool = &pool_tbl->pool[i]; >>>> + LOCK_INIT(&pool->s.lock); >>>> + pool->s.pool = i; >>>> + >>>> + pool_entry_ptr[i] = pool; >>>> + } >>>> + >>>> + ODP_DBG("\nBuffer pool init global\n"); >>>> + ODP_DBG(" pool_entry_s size %zu\n", sizeof(struct >>>> pool_entry_s)); >>>> + ODP_DBG(" pool_entry_t size %zu\n", sizeof(pool_entry_t)); >>>> + ODP_DBG(" odp_buffer_hdr_t size %zu\n", >>>> sizeof(odp_buffer_hdr_t)); >>>> + ODP_DBG("\n"); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> + >>>> +odp_buffer_pool_t odp_buffer_pool_create(const char *name, >>>> + void *base_addr, uint64_t size, >>>> + size_t buf_size, size_t >>>> buf_align, >>>> + int buf_type) >>>> +{ >>>> + struct rte_mempool *pktmbuf_pool = NULL; >>>> + ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n", >>>> name, >>>> + (uint64_t) base_addr, (unsigned) size, >>>> + (unsigned) buf_size, (unsigned) buf_align, >>>> + buf_type); >>>> + >>>> + pktmbuf_pool = >>>> + rte_mempool_create(name, NB_MBUF, >>>> + MBUF_SIZE, 32, >>>> + sizeof(struct >>>> rte_pktmbuf_pool_private), >>>> + rte_pktmbuf_pool_init, NULL, >>>> + rte_pktmbuf_init, NULL, >>>> + rte_socket_id(), 0); >>>> + if (pktmbuf_pool == NULL) { >>>> + ODP_ERR("Cannot init DPDK mbuf pool\n"); >>>> + return -1; >>>> + } >>>> + >>>> + return (odp_buffer_pool_t) pktmbuf_pool; >>>> +} >>>> + >>>> + >>>> +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name) >>>> +{ >>>> + struct rte_mempool *mp = NULL; >>>> + >>>> + mp = rte_mempool_lookup(name); >>>> + if (mp == NULL) >>>> + return ODP_BUFFER_POOL_INVALID; >>>> + >>>> + return (odp_buffer_pool_t)mp; >>>> +} >>>> + >>>> + >>>> +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id) >>>> +{ >>>> + return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool >>>> *)pool_id); >>>> +} >>>> + >>>> + >>>> +void odp_buffer_free(odp_buffer_t buf) >>>> +{ >>>> + rte_pktmbuf_free((struct rte_mbuf *)buf); >>>> +} >>>> + >>>> + >>>> +void odp_buffer_pool_print(odp_buffer_pool_t pool_id) >>>> +{ >>>> + rte_mempool_dump((const struct rte_mempool *)pool_id); >>>> +} >>>> diff --git a/platform/linux-dpdk/source/odp_init.c >>>> b/platform/linux-dpdk/source/odp_init.c >>>> new file mode 100644 >>>> index 0000000..ecc2066 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/source/odp_init.c >>>> @@ -0,0 +1,113 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#include <odp_init.h> >>>> +#include <odp_internal.h> >>>> +#include <odp_debug.h> >>>> +#include <odp_packet_dpdk.h> >>>> + >>>> +int odp_init_dpdk(void) >>>> +{ >>>> + int test_argc = 5; >>>> + char *test_argv[6]; >>>> + int core_count, i, num_cores = 0; >>>> + char core_mask[8]; >>>> + >>>> + core_count = odp_sys_core_count(); >>>> + for (i = 0; i < core_count; i++) >>>> + num_cores += (0x1 << i); >>>> + sprintf(core_mask, "%x", num_cores); >>>> + >>>> + test_argv[0] = malloc(sizeof("odp_dpdk")); >>>> + strcpy(test_argv[0], "odp_dpdk"); >>>> + test_argv[1] = malloc(sizeof("-c")); >>>> + strcpy(test_argv[1], "-c"); >>>> + test_argv[2] = malloc(sizeof(core_mask)); >>>> + strcpy(test_argv[2], core_mask); >>>> + test_argv[3] = malloc(sizeof("-n")); >>>> + strcpy(test_argv[3], "-n"); >>>> + test_argv[4] = malloc(sizeof("3")); >>>> + strcpy(test_argv[4], "3"); >>>> + >>>> + if (rte_eal_init(test_argc, (char **)test_argv) < 0) { >>>> + ODP_ERR("Cannot init the Intel DPDK EAL!"); >>>> + return -1; >>>> + } >>>> + >>>> + if (rte_pmd_init_all() < 0) { >>>> + ODP_ERR("Cannot init pmd\n"); >>>> + return -1; >>>> + } >>>> + >>>> + if (rte_eal_pci_probe() < 0) { >>>> + ODP_ERR("Cannot probe PCI\n"); >>>> + return -1; >>>> + } >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +int odp_init_global(void) >>>> +{ >>>> + odp_thread_init_global(); >>>> + >>>> + odp_system_info_init(); >>>> + >>>> + if (odp_init_dpdk()) { >>>> + ODP_ERR("ODP dpdk init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + if (odp_shm_init_global()) { >>>> + ODP_ERR("ODP shm init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + if (odp_buffer_pool_init_global()) { >>>> + ODP_ERR("ODP buffer pool init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + if (odp_queue_init_global()) { >>>> + ODP_ERR("ODP queue init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + if (odp_schedule_init_global()) { >>>> + ODP_ERR("ODP schedule init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + if (odp_pktio_init_global()) { >>>> + ODP_ERR("ODP packet io init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + if (odp_timer_init_global()) { >>>> + ODP_ERR("ODP timer init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + return 0; >>>> +} >>>> + >>>> + >>>> +int odp_init_local(int thr_id) >>>> +{ >>>> + odp_thread_init_local(thr_id); >>>> + >>>> + if (odp_pktio_init_local()) { >>>> + ODP_ERR("ODP packet io local init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + if (odp_schedule_init_local()) { >>>> + ODP_ERR("ODP schedule local init failed.\n"); >>>> + return -1; >>>> + } >>>> + >>>> + return 0; >>>> +} >>>> diff --git a/platform/linux-dpdk/source/odp_packet.c >>>> b/platform/linux-dpdk/source/odp_packet.c >>>> new file mode 100644 >>>> index 0000000..c34e626 >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/source/odp_packet.c >>>> @@ -0,0 +1,374 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#include <odp_packet.h> >>>> +#include <odp_packet_internal.h> >>>> +#include <odp_hints.h> >>>> +#include <odp_byteorder.h> >>>> + >>>> +#include <helper/odp_eth.h> >>>> +#include <helper/odp_ip.h> >>>> + >>>> +#include <string.h> >>>> +#include <stdio.h> >>>> + >>>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, >>>> odp_ipv4hdr_t *ipv4, >>>> + size_t *offset_out); >>>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, >>>> odp_ipv6hdr_t *ipv6, >>>> + size_t *offset_out); >>>> + >>>> +void odp_packet_init(odp_packet_t pkt) >>>> +{ >>>> + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); >>>> + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, >>>> buf_hdr); >>>> + uint8_t *start; >>>> + size_t len; >>>> + >>>> + start = (uint8_t *)pkt_hdr + start_offset; >>>> + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; >>>> + memset(start, 0, len); >>>> + >>>> + pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >>>> + pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >>>> + pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; >>>> +} >>>> + >>>> +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf) >>>> +{ >>>> + return (odp_packet_t)buf; >>>> +} >>>> + >>>> +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt) >>>> +{ >>>> + return (odp_buffer_t)pkt; >>>> +} >>>> + >>>> +void odp_packet_set_len(odp_packet_t pkt, size_t len) >>>> +{ >>>> + /* for rte_pktmbuf */ >>>> + odp_buffer_hdr_t *buf_hdr = >>>> odp_buf_to_hdr(odp_buffer_from_packet(pkt)); >>>> + buf_hdr->pkt.data_len = len; >>>> + >>>> + odp_packet_hdr(pkt)->frame_len = len; >>>> +} >>>> + >>>> +size_t odp_packet_get_len(odp_packet_t pkt) >>>> +{ >>>> + return odp_packet_hdr(pkt)->frame_len; >>>> +} >>>> + >>>> +uint8_t *odp_packet_buf_addr(odp_packet_t pkt) >>>> +{ >>>> + return odp_buffer_addr(odp_buffer_from_packet(pkt)); >>>> +} >>>> + >>>> +uint8_t *odp_packet_start(odp_packet_t pkt) >>>> +{ >>>> + return odp_packet_buf_addr(pkt) + >>>> odp_packet_hdr(pkt)->frame_offset; >>>> +} >>>> + >>>> + >>>> +uint8_t *odp_packet_l2(odp_packet_t pkt) >>>> +{ >>>> + const size_t offset = odp_packet_l2_offset(pkt); >>>> + >>>> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >>>> + return NULL; >>>> + >>>> + return odp_packet_buf_addr(pkt) + offset; >>>> +} >>>> + >>>> +size_t odp_packet_l2_offset(odp_packet_t pkt) >>>> +{ >>>> + return odp_packet_hdr(pkt)->l2_offset; >>>> +} >>>> + >>>> +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset) >>>> +{ >>>> + odp_packet_hdr(pkt)->l2_offset = offset; >>>> +} >>>> + >>>> +uint8_t *odp_packet_l3(odp_packet_t pkt) >>>> +{ >>>> + const size_t offset = odp_packet_l3_offset(pkt); >>>> + >>>> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >>>> + return NULL; >>>> + >>>> + return odp_packet_buf_addr(pkt) + offset; >>>> +} >>>> + >>>> +size_t odp_packet_l3_offset(odp_packet_t pkt) >>>> +{ >>>> + return odp_packet_hdr(pkt)->l3_offset; >>>> +} >>>> + >>>> +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset) >>>> +{ >>>> + odp_packet_hdr(pkt)->l3_offset = offset; >>>> +} >>>> + >>>> +uint8_t *odp_packet_l4(odp_packet_t pkt) >>>> +{ >>>> + const size_t offset = odp_packet_l4_offset(pkt); >>>> + >>>> + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) >>>> + return NULL; >>>> + >>>> + return odp_packet_buf_addr(pkt) + offset; >>>> +} >>>> + >>>> +size_t odp_packet_l4_offset(odp_packet_t pkt) >>>> +{ >>>> + return odp_packet_hdr(pkt)->l4_offset; >>>> +} >>>> + >>>> +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset) >>>> +{ >>>> + odp_packet_hdr(pkt)->l4_offset = offset; >>>> +} >>>> + >>>> +/** >>>> + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP >>>> + * >>>> + * Internal function: caller is resposible for passing only valid >>>> packet handles >>>> + * , lengths and offsets (usually done&called in packet input). >>>> + * >>>> + * @param pkt Packet handle >>>> + * @param len Packet length in bytes >>>> + * @param frame_offset Byte offset to L2 header >>>> + */ >>>> +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t >>>> frame_offset) >>>> +{ >>>> + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); >>>> + odp_ethhdr_t *eth; >>>> + odp_vlanhdr_t *vlan; >>>> + odp_ipv4hdr_t *ipv4; >>>> + odp_ipv6hdr_t *ipv6; >>>> + uint16_t ethtype; >>>> + size_t offset = 0; >>>> + uint8_t ip_proto = 0; >>>> + >>>> + pkt_hdr->input_flags.eth = 1; >>>> + pkt_hdr->frame_offset = frame_offset; >>>> + pkt_hdr->frame_len = len; >>>> + >>>> + if (odp_unlikely(len < ODP_ETH_LEN_MIN)) { >>>> + pkt_hdr->error_flags.frame_len = 1; >>>> + return; >>>> + } else if (len > ODP_ETH_LEN_MAX) { >>>> + pkt_hdr->input_flags.jumbo = 1; >>>> + } >>>> + >>>> + /* Assume valid L2 header, no CRC/FCS check in SW */ >>>> + pkt_hdr->input_flags.l2 = 1; >>>> + pkt_hdr->l2_offset = frame_offset; >>>> + >>>> + eth = (odp_ethhdr_t *)odp_packet_start(pkt); >>>> + ethtype = odp_be_to_cpu_16(eth->type); >>>> + vlan = (odp_vlanhdr_t *)ð->type; >>>> + >>>> + if (ethtype == ODP_ETHTYPE_VLAN_OUTER) { >>>> + pkt_hdr->input_flags.vlan_qinq = 1; >>>> + ethtype = odp_be_to_cpu_16(vlan->tpid); >>>> + offset += sizeof(odp_vlanhdr_t); >>>> + vlan = &vlan[1]; >>>> + } >>>> + >>>> + if (ethtype == ODP_ETHTYPE_VLAN) { >>>> + pkt_hdr->input_flags.vlan = 1; >>>> + ethtype = odp_be_to_cpu_16(vlan->tpid); >>>> + offset += sizeof(odp_vlanhdr_t); >>>> + } >>>> + >>>> + /* Set l3_offset+flag only for known ethtypes */ >>>> + switch (ethtype) { >>>> + case ODP_ETHTYPE_IPV4: >>>> + pkt_hdr->input_flags.ipv4 = 1; >>>> + pkt_hdr->input_flags.l3 = 1; >>>> + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + >>>> offset; >>>> + ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt); >>>> + ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset); >>>> + break; >>>> + case ODP_ETHTYPE_IPV6: >>>> + pkt_hdr->input_flags.ipv6 = 1; >>>> + pkt_hdr->input_flags.l3 = 1; >>>> + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + >>>> offset; >>>> + ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt); >>>> + ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset); >>>> + break; >>>> + case ODP_ETHTYPE_ARP: >>>> + pkt_hdr->input_flags.arp = 1; >>>> + /* fall through */ >>>> + default: >>>> + ip_proto = 0; >>>> + break; >>>> + } >>>> + >>>> + switch (ip_proto) { >>>> + case ODP_IPPROTO_UDP: >>>> + pkt_hdr->input_flags.udp = 1; >>>> + pkt_hdr->input_flags.l4 = 1; >>>> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >>>> + break; >>>> + case ODP_IPPROTO_TCP: >>>> + pkt_hdr->input_flags.tcp = 1; >>>> + pkt_hdr->input_flags.l4 = 1; >>>> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >>>> + break; >>>> + case ODP_IPPROTO_SCTP: >>>> + pkt_hdr->input_flags.sctp = 1; >>>> + pkt_hdr->input_flags.l4 = 1; >>>> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >>>> + break; >>>> + case ODP_IPPROTO_ICMP: >>>> + pkt_hdr->input_flags.icmp = 1; >>>> + pkt_hdr->input_flags.l4 = 1; >>>> + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; >>>> + break; >>>> + default: >>>> + /* 0 or unhandled IP protocols, don't set L4 >>>> flag+offset */ >>>> + if (pkt_hdr->input_flags.ipv6) { >>>> + /* IPv6 next_hdr is not L4, mark as IP-option >>>> instead */ >>>> + pkt_hdr->input_flags.ipopt = 1; >>>> + } >>>> + break; >>>> + } >>>> +} >>>> + >>>> +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, >>>> odp_ipv4hdr_t *ipv4, >>>> + size_t *offset_out) >>>> +{ >>>> + uint8_t ihl; >>>> + uint16_t frag_offset; >>>> + >>>> + ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl); >>>> + if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) { >>>> + pkt_hdr->error_flags.ip_err = 1; >>>> + return 0; >>>> + } >>>> + >>>> + if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) { >>>> + pkt_hdr->input_flags.ipopt = 1; >>>> + return 0; >>>> + } >>>> + >>>> + /* A packet is a fragment if: >>>> + * "more fragments" flag is set (all fragments except the last) >>>> + * OR >>>> + * "fragment offset" field is nonzero (all fragments except the >>>> first) >>>> + */ >>>> + frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); >>>> + if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) { >>>> + pkt_hdr->input_flags.ipfrag = 1; >>>> + return 0; >>>> + } >>>> + >>>> + if (ipv4->proto == ODP_IPPROTO_ESP || >>>> + ipv4->proto == ODP_IPPROTO_AH) { >>>> + pkt_hdr->input_flags.ipsec = 1; >>>> + return 0; >>>> + } >>>> + >>>> + /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after >>>> return */ >>>> + >>>> + *offset_out = sizeof(uint32_t) * ihl; >>>> + return ipv4->proto; >>>> +} >>>> + >>>> +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, >>>> odp_ipv6hdr_t *ipv6, >>>> + size_t *offset_out) >>>> +{ >>>> + if (ipv6->next_hdr == ODP_IPPROTO_ESP || >>>> + ipv6->next_hdr == ODP_IPPROTO_AH) { >>>> + pkt_hdr->input_flags.ipopt = 1; >>>> + pkt_hdr->input_flags.ipsec = 1; >>>> + return 0; >>>> + } >>>> + >>>> + if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) { >>>> + pkt_hdr->input_flags.ipopt = 1; >>>> + pkt_hdr->input_flags.ipfrag = 1; >>>> + return 0; >>>> + } >>>> + >>>> + /* Don't step through more extensions */ >>>> + *offset_out = ODP_IPV6HDR_LEN; >>>> + return ipv6->next_hdr; >>>> +} >>>> + >>>> +void odp_packet_print(odp_packet_t pkt) >>>> +{ >>>> + int max_len = 512; >>>> + char str[max_len]; >>>> + int len = 0; >>>> + int n = max_len-1; >>>> + odp_packet_hdr_t *hdr = odp_packet_hdr(pkt); >>>> + >>>> + len += snprintf(&str[len], n-len, "Packet "); >>>> + len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt); >>>> + len += snprintf(&str[len], n-len, >>>> + " input_flags 0x%x\n", hdr->input_flags.all); >>>> + len += snprintf(&str[len], n-len, >>>> + " error_flags 0x%x\n", hdr->error_flags.all); >>>> + len += snprintf(&str[len], n-len, >>>> + " output_flags 0x%x\n", hdr->output_flags.all); >>>> + len += snprintf(&str[len], n-len, >>>> + " frame_offset %u\n", hdr->frame_offset); >>>> + len += snprintf(&str[len], n-len, >>>> + " l2_offset %u\n", hdr->l2_offset); >>>> + len += snprintf(&str[len], n-len, >>>> + " l3_offset %u\n", hdr->l3_offset); >>>> + len += snprintf(&str[len], n-len, >>>> + " l4_offset %u\n", hdr->l4_offset); >>>> + len += snprintf(&str[len], n-len, >>>> + " frame_len %u\n", hdr->frame_len); >>>> + len += snprintf(&str[len], n-len, >>>> + " input %u\n", hdr->input); >>>> + str[len] = '\0'; >>>> + >>>> + printf("\n%s\n", str); >>>> +} >>>> + >>>> +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src) >>>> +{ >>>> + odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst); >>>> + odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src); >>>> + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, >>>> buf_hdr); >>>> + uint8_t *start_src; >>>> + uint8_t *start_dst; >>>> + size_t len; >>>> + >>>> + if (pkt_dst == ODP_PACKET_INVALID || pkt_src == >>>> ODP_PACKET_INVALID) >>>> + return -1; >>>> + >>>> + /* if (pkt_hdr_dst->buf_hdr.size < */ >>>> + /* pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */ >>>> + if (pkt_hdr_dst->buf_hdr.buf_len < >>>> + pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) >>>> + return -1; >>>> + >>>> + /* Copy packet header */ >>>> + start_dst = (uint8_t *)pkt_hdr_dst + start_offset; >>>> + start_src = (uint8_t *)pkt_hdr_src + start_offset; >>>> + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; >>>> + memcpy(start_dst, start_src, len); >>>> + >>>> + /* Copy frame payload */ >>>> + start_dst = (uint8_t *)odp_packet_start(pkt_dst); >>>> + start_src = (uint8_t *)odp_packet_start(pkt_src); >>>> + len = pkt_hdr_src->frame_len; >>>> + memcpy(start_dst, start_src, len); >>>> + >>>> + /* Copy useful things from the buffer header */ >>>> + /* pkt_hdr_dst->buf_hdr.cur_offset = >>>> pkt_hdr_src->buf_hdr.cur_offset; */ >>>> + >>>> + /* Create a copy of the scatter list */ >>>> + /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */ >>>> + /* odp_buffer_from_packet(pkt_src)); */ >>>> + >>>> + return 0; >>>> +} >>>> diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c >>>> b/platform/linux-dpdk/source/odp_packet_dpdk.c >>>> new file mode 100644 >>>> index 0000000..6d16bbe >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c >>>> @@ -0,0 +1,177 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#define _GNU_SOURCE >>>> +#include <stdio.h> >>>> +#include <errno.h> >>>> +#include <sys/types.h> >>>> +#include <sys/stat.h> >>>> +#include <sys/ioctl.h> >>>> +#include <sys/mman.h> >>>> +#include <poll.h> >>>> +#include <unistd.h> >>>> +#include <fcntl.h> >>>> +#include <string.h> >>>> +#include <stdlib.h> >>>> + >>>> +#include <linux/ethtool.h> >>>> +#include <linux/sockios.h> >>>> + >>>> +#include <odp_hints.h> >>>> +#include <odp_thread.h> >>>> + >>>> +#include <odp_packet_dpdk.h> >>>> +#include <net/if.h> >>>> + >>>> +/* >>>> + * RX and TX Prefetch, Host, and Write-back threshold values should be >>>> + * carefully set for optimal performance. Consult the network >>>> + * controller's datasheet and supporting DPDK documentation for >>>> guidance >>>> + * on how these parameters should be set. >>>> + */ >>>> +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. >>>> */ >>>> +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ >>>> +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold >>>> reg. */ >>>> + >>>> +/* >>>> + * These default values are optimized for use with the Intel(R) 82599 >>>> 10 GbE >>>> + * Controller and the DPDK ixgbe PMD. Consider using other values for >>>> other >>>> + * network controllers and/or network drivers. >>>> + */ >>>> +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold >>>> reg. */ >>>> +#define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ >>>> +#define TX_WTHRESH 0 /**< Default values of TX write-back threshold >>>> reg. */ >>>> + >>>> +#define MAX_PKT_BURST 32 >>>> +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ >>>> +#define RTE_TEST_RX_DESC_DEFAULT 128 >>>> +#define RTE_TEST_TX_DESC_DEFAULT 512 >>>> +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; >>>> +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; >>>> + >>>> +static const struct rte_eth_conf port_conf = { >>>> + .rxmode = { >>>> + .split_hdr_size = 0, >>>> + .header_split = 0, /**< Header Split disabled */ >>>> + .hw_ip_checksum = 0, /**< IP checksum offload disabled >>>> */ >>>> + .hw_vlan_filter = 0, /**< VLAN filtering disabled */ >>>> + .jumbo_frame = 0, /**< Jumbo Frame Support disabled >>>> */ >>>> + .hw_strip_crc = 0, /**< CRC stripped by hardware */ >>>> + }, >>>> + .txmode = { >>>> + .mq_mode = ETH_MQ_TX_NONE, >>>> + }, >>>> +}; >>>> + >>>> +static const struct rte_eth_rxconf rx_conf = { >>>> + .rx_thresh = { >>>> + .pthresh = RX_PTHRESH, >>>> + .hthresh = RX_HTHRESH, >>>> + .wthresh = RX_WTHRESH, >>>> + }, >>>> +}; >>>> + >>>> +static const struct rte_eth_txconf tx_conf = { >>>> + .tx_thresh = { >>>> + .pthresh = TX_PTHRESH, >>>> + .hthresh = TX_HTHRESH, >>>> + .wthresh = TX_WTHRESH, >>>> + }, >>>> + .tx_free_thresh = 0, /* Use PMD default values */ >>>> + .tx_rs_thresh = 0, /* Use PMD default values */ >>>> + /* >>>> + * As the example won't handle mult-segments and offload cases, >>>> + * set the flag by default. >>>> + */ >>>> + .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | >>>> ETH_TXQ_FLAGS_NOOFFLOADS, >>>> +}; >>>> + >>>> +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, >>>> + odp_buffer_pool_t pool) >>>> +{ >>>> + ODP_DBG("setup_pkt_dpdk\n"); >>>> + >>>> + static struct ether_addr eth_addr[RTE_MAX_ETHPORTS]; >>>> + uint8_t portid = 0; >>>> + uint16_t queueid = 0; >>>> + int ret; >>>> + printf("vincent netdev: %s\n", netdev); >>>> + printf("vincent pool: %lx\n", pool); >>>> + >>>> + portid = atoi(netdev); >>>> + pkt_dpdk->portid = portid; >>>> + pkt_dpdk->queueid = queueid; >>>> + pkt_dpdk->pool = pool; >>>> + printf("vincent portid: %u\n", portid); >>>> + >>>> + fflush(stdout); >>>> + ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); >>>> + if (ret < 0) >>>> + ODP_ERR("Cannot configure device: err=%d, port=%u\n", >>>> + ret, (unsigned) portid); >>>> + >>>> + rte_eth_macaddr_get(portid, ð_addr[portid]); >>>> + ODP_DBG("Port %u, MAC address: >>>> %02X:%02X:%02X:%02X:%02X:%02X\n\n", >>>> + (unsigned) portid, >>>> + eth_addr[portid].addr_bytes[0], >>>> + eth_addr[portid].addr_bytes[1], >>>> + eth_addr[portid].addr_bytes[2], >>>> + eth_addr[portid].addr_bytes[3], >>>> + eth_addr[portid].addr_bytes[4], >>>> + eth_addr[portid].addr_bytes[5]); >>>> + >>>> + /* init one RX queue on each port */ >>>> + fflush(stdout); >>>> + ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, >>>> + rte_eth_dev_socket_id(portid), >>>> &rx_conf, >>>> + (struct rte_mempool *)pool); >>>> + if (ret < 0) >>>> + ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n", >>>> + ret, (unsigned) portid); >>>> + ODP_DBG("dpdk rx queue setup done\n"); >>>> + >>>> + /* init one TX queue on each port */ >>>> + fflush(stdout); >>>> + ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, >>>> + rte_eth_dev_socket_id(portid), &tx_conf); >>>> + if (ret < 0) >>>> + ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n", >>>> + ret, (unsigned) portid); >>>> + ODP_DBG("dpdk tx queue setup done\n"); >>>> + >>>> + /* Start device */ >>>> + ret = rte_eth_dev_start(portid); >>>> + if (ret < 0) >>>> + ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n", >>>> + ret, (unsigned) portid); >>>> + ODP_DBG("dpdk setup done\n\n"); >>>> + >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk) >>>> +{ >>>> + ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t >>>> pkt_table[], >>>> + unsigned len) >>>> +{ >>>> + return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid, >>>> + (uint16_t)pkt_dpdk->queueid, >>>> + (struct rte_mbuf **)pkt_table, >>>> (uint16_t)len); >>>> +} >>>> + >>>> +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t >>>> pkt_table[], >>>> + unsigned len) >>>> +{ >>>> + return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid, >>>> + (uint16_t)pkt_dpdk->queueid, >>>> + (struct rte_mbuf **)pkt_table, >>>> (uint16_t)len); >>>> +} >>>> diff --git a/platform/linux-dpdk/source/odp_packet_io.c >>>> b/platform/linux-dpdk/source/odp_packet_io.c >>>> new file mode 100644 >>>> index 0000000..abea0ec >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/source/odp_packet_io.c >>>> @@ -0,0 +1,561 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#include <odp_packet_io.h> >>>> +#include <odp_packet_io_internal.h> >>>> +#include <odp_packet_io_queue.h> >>>> +#include <odp_packet.h> >>>> +#include <odp_packet_internal.h> >>>> +#include <odp_internal.h> >>>> +#include <odp_spinlock.h> >>>> +#include <odp_shared_memory.h> >>>> +#include <odp_packet_socket.h> >>>> +#ifdef ODP_HAVE_NETMAP >>>> +#include <odp_packet_netmap.h> >>>> +#endif >>>> +#include <odp_hints.h> >>>> +#include <odp_config.h> >>>> +#include <odp_queue_internal.h> >>>> +#include <odp_schedule_internal.h> >>>> +#include <odp_debug.h> >>>> + >>>> +#include <odp_pktio_socket.h> >>>> +#ifdef ODP_HAVE_NETMAP >>>> +#include <odp_pktio_netmap.h> >>>> +#endif >>>> + >>>> +#include <string.h> >>>> + >>>> +typedef struct { >>>> + pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES]; >>>> +} pktio_table_t; >>>> + >>>> +static pktio_table_t *pktio_tbl; >>>> + >>>> + >>>> +static pktio_entry_t *get_entry(odp_pktio_t id) >>>> +{ >>>> + if (odp_unlikely(id == ODP_PKTIO_INVALID || >>>> + id > ODP_CONFIG_PKTIO_ENTRIES)) >>>> + return NULL; >>>> + >>>> + return &pktio_tbl->entries[id - 1]; >>>> +} >>>> + >>>> +int odp_pktio_init_global(void) >>>> +{ >>>> + char name[ODP_QUEUE_NAME_LEN]; >>>> + pktio_entry_t *pktio_entry; >>>> + queue_entry_t *queue_entry; >>>> + odp_queue_t qid; >>>> + int id; >>>> + >>>> + pktio_tbl = odp_shm_reserve("odp_pktio_entries", >>>> + sizeof(pktio_table_t), >>>> + sizeof(pktio_entry_t)); >>>> + if (pktio_tbl == NULL) >>>> + return -1; >>>> + >>>> + memset(pktio_tbl, 0, sizeof(pktio_table_t)); >>>> + >>>> + for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) { >>>> + pktio_entry = get_entry(id); >>>> + >>>> + odp_spinlock_init(&pktio_entry->s.lock); >>>> + >>>> + /* Create a default output queue for each pktio >>>> resource */ >>>> + snprintf(name, sizeof(name), "%i-pktio_outq_default", >>>> (int)id); >>>> + name[ODP_QUEUE_NAME_LEN-1] = '\0'; >>>> + >>>> + qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, >>>> NULL); >>>> + if (qid == ODP_QUEUE_INVALID) >>>> + return -1; >>>> + pktio_entry->s.outq_default = qid; >>>> + >>>> + queue_entry = queue_to_qentry(qid); >>>> + queue_entry->s.pktout = id; >>>> + } >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +int odp_pktio_init_local(void) >>>> +{ >>>> + return 0; >>>> +} >>>> + >>>> +static int is_free(pktio_entry_t *entry) >>>> +{ >>>> + return (entry->s.taken == 0); >>>> +} >>>> + >>>> +static void set_free(pktio_entry_t *entry) >>>> +{ >>>> + entry->s.taken = 0; >>>> +} >>>> + >>>> +static void set_taken(pktio_entry_t *entry) >>>> +{ >>>> + entry->s.taken = 1; >>>> +} >>>> + >>>> +static void lock_entry(pktio_entry_t *entry) >>>> +{ >>>> + odp_spinlock_lock(&entry->s.lock); >>>> +} >>>> + >>>> +static void unlock_entry(pktio_entry_t *entry) >>>> +{ >>>> + odp_spinlock_unlock(&entry->s.lock); >>>> +} >>>> + >>>> +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t >>>> *params) >>>> +{ >>>> + set_taken(entry); >>>> + entry->s.inq_default = ODP_QUEUE_INVALID; >>>> + switch (params->type) { >>>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>>> + memset(&entry->s.pkt_sock, 0, >>>> sizeof(entry->s.pkt_sock)); >>>> + memset(&entry->s.pkt_sock_mmap, 0, >>>> + sizeof(entry->s.pkt_sock_mmap)); >>>> + break; >>>> +#ifdef ODP_HAVE_NETMAP >>>> + case ODP_PKTIO_TYPE_NETMAP: >>>> + memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm)); >>>> + break; >>>> +#endif >>>> + case ODP_PKTIO_TYPE_DPDK: >>>> + memset(&entry->s.pkt_dpdk, 0, >>>> sizeof(entry->s.pkt_dpdk)); >>>> + break; >>>> + default: >>>> + ODP_ERR("Packet I/O type not supported. Please >>>> recompile\n"); >>>> + break; >>>> + } >>>> + /* Save pktio parameters, type is the most useful */ >>>> + memcpy(&entry->s.params, params, sizeof(*params)); >>>> +} >>>> + >>>> +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params) >>>> +{ >>>> + odp_pktio_t id; >>>> + pktio_entry_t *entry; >>>> + int i; >>>> + >>>> + for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) { >>>> + entry = &pktio_tbl->entries[i]; >>>> + if (is_free(entry)) { >>>> + lock_entry(entry); >>>> + if (is_free(entry)) { >>>> + init_pktio_entry(entry, params); >>>> + id = i + 1; >>>> + return id; /* return with entry locked! >>>> */ >>>> + } >>>> + unlock_entry(entry); >>>> + } >>>> + } >>>> + >>>> + return ODP_PKTIO_INVALID; >>>> +} >>>> + >>>> +static int free_pktio_entry(odp_pktio_t id) >>>> +{ >>>> + pktio_entry_t *entry = get_entry(id); >>>> + >>>> + if (entry == NULL) >>>> + return -1; >>>> + >>>> + set_free(entry); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool, >>>> + odp_pktio_params_t *params) >>>> +{ >>>> + odp_pktio_t id; >>>> + pktio_entry_t *pktio_entry; >>>> + int res; >>>> + >>>> + if (params == NULL) { >>>> + ODP_ERR("Invalid pktio params\n"); >>>> + return ODP_PKTIO_INVALID; >>>> + } >>>> + >>>> + switch (params->type) { >>>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>>> + ODP_DBG("Allocating socket pktio\n"); >>>> + break; >>>> +#ifdef ODP_HAVE_NETMAP >>>> + case ODP_PKTIO_TYPE_NETMAP: >>>> + ODP_DBG("Allocating netmap pktio\n"); >>>> + break; >>>> +#endif >>>> + case ODP_PKTIO_TYPE_DPDK: >>>> + ODP_DBG("Allocating dpdk pktio\n"); >>>> + break; >>>> + default: >>>> + ODP_ERR("Invalid pktio type: %02x\n", params->type); >>>> + return ODP_PKTIO_INVALID; >>>> + } >>>> + >>>> + id = alloc_lock_pktio_entry(params); >>>> + if (id == ODP_PKTIO_INVALID) { >>>> + ODP_ERR("No resources available.\n"); >>>> + return ODP_PKTIO_INVALID; >>>> + } >>>> + /* if successful, alloc_pktio_entry() returns with the entry >>>> locked */ >>>> + >>>> + pktio_entry = get_entry(id); >>>> + >>>> + switch (params->type) { >>>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>>> + res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, >>>> pool); >>>> + if (res == -1) { >>>> + close_pkt_sock(&pktio_entry->s.pkt_sock); >>>> + free_pktio_entry(id); >>>> + id = ODP_PKTIO_INVALID; >>>> + } >>>> + break; >>>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>>> + res = >>>> setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, dev, >>>> + pool, params->sock_params.fanout); >>>> + if (res == -1) { >>>> + >>>> close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap); >>>> + free_pktio_entry(id); >>>> + id = ODP_PKTIO_INVALID; >>>> + } >>>> + break; >>>> +#ifdef ODP_HAVE_NETMAP >>>> + case ODP_PKTIO_TYPE_NETMAP: >>>> + >>>> + res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev, >>>> + pool, ¶ms->nm_params); >>>> + if (res == -1) { >>>> + close_pkt_netmap(&pktio_entry->s.pkt_nm); >>>> + free_pktio_entry(id); >>>> + id = ODP_PKTIO_INVALID; >>>> + } >>>> + break; >>>> +#endif >>>> + case ODP_PKTIO_TYPE_DPDK: >>>> + res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, >>>> pool); >>>> + if (res == -1) { >>>> + close_pkt_dpdk(&pktio_entry->s.pkt_dpdk); >>>> + free_pktio_entry(id); >>>> + id = ODP_PKTIO_INVALID; >>>> + } >>>> + break; >>>> + default: >>>> + free_pktio_entry(id); >>>> + id = ODP_PKTIO_INVALID; >>>> + ODP_ERR("Invalid pktio type. Please recompile.\n"); >>>> + break; >>>> + } >>>> + >>>> + unlock_entry(pktio_entry); >>>> + return id; >>>> +} >>>> + >>>> +int odp_pktio_close(odp_pktio_t id) >>>> +{ >>>> + pktio_entry_t *entry; >>>> + int res = -1; >>>> + >>>> + entry = get_entry(id); >>>> + if (entry == NULL) >>>> + return -1; >>>> + >>>> + lock_entry(entry); >>>> + if (!is_free(entry)) { >>>> + switch (entry->s.params.type) { >>>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>>> + res = close_pkt_sock(&entry->s.pkt_sock); >>>> + break; >>>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>>> + res = >>>> close_pkt_sock_mmap(&entry->s.pkt_sock_mmap); >>>> + break; >>>> +#ifdef ODP_HAVE_NETMAP >>>> + case ODP_PKTIO_TYPE_NETMAP: >>>> + res = close_pkt_netmap(&entry->s.pkt_nm); >>>> + break; >>>> +#endif >>>> + case ODP_PKTIO_TYPE_DPDK: >>>> + res = close_pkt_dpdk(&entry->s.pkt_dpdk); >>>> + break; >>>> + default: >>>> + break; >>>> + res |= free_pktio_entry(id); >>>> + } >>>> + } >>>> + unlock_entry(entry); >>>> + >>>> + if (res != 0) >>>> + return -1; >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio) >>>> +{ >>>> + odp_packet_hdr(pkt)->input = pktio; >>>> +} >>>> + >>>> +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt) >>>> +{ >>>> + return odp_packet_hdr(pkt)->input; >>>> +} >>>> + >>>> +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned >>>> len) >>>> +{ >>>> + pktio_entry_t *pktio_entry = get_entry(id); >>>> + int pkts; >>>> + int i; >>>> + >>>> + if (pktio_entry == NULL) >>>> + return -1; >>>> + >>>> + lock_entry(pktio_entry); >>>> + switch (pktio_entry->s.params.type) { >>>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>>> + pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock, >>>> + pkt_table, len); >>>> + break; >>>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>>> + pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, >>>> + pkt_table, len); >>>> + break; >>>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>>> + pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, >>>> + pkt_table, len); >>>> + break; >>>> +#ifdef ODP_HAVE_NETMAP >>>> + case ODP_PKTIO_TYPE_NETMAP: >>>> + pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm, >>>> pkt_table, len); >>>> + break; >>>> +#endif >>>> + case ODP_PKTIO_TYPE_DPDK: >>>> + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, >>>> pkt_table, len); >>>> + break; >>>> + default: >>>> + pkts = -1; >>>> + break; >>>> + } >>>> + >>>> + unlock_entry(pktio_entry); >>>> + if (pkts < 0) >>>> + return pkts; >>>> + >>>> + for (i = 0; i < pkts; ++i) >>>> + odp_pktio_set_input(pkt_table[i], id); >>>> + >>>> + return pkts; >>>> +} >>>> + >>>> +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned >>>> len) >>>> +{ >>>> + pktio_entry_t *pktio_entry = get_entry(id); >>>> + int pkts; >>>> + >>>> + if (pktio_entry == NULL) >>>> + return -1; >>>> + >>>> + lock_entry(pktio_entry); >>>> + switch (pktio_entry->s.params.type) { >>>> + case ODP_PKTIO_TYPE_SOCKET_BASIC: >>>> + pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock, >>>> + pkt_table, len); >>>> + break; >>>> + case ODP_PKTIO_TYPE_SOCKET_MMSG: >>>> + pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, >>>> + pkt_table, len); >>>> + break; >>>> + case ODP_PKTIO_TYPE_SOCKET_MMAP: >>>> + pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, >>>> + pkt_table, len); >>>> + break; >>>> +#ifdef ODP_HAVE_NETMAP >>>> + case ODP_PKTIO_TYPE_NETMAP: >>>> + pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm, >>>> + pkt_table, len); >>>> + break; >>>> +#endif >>>> + case ODP_PKTIO_TYPE_DPDK: >>>> + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, >>>> + pkt_table, len); >>>> + break; >>>> + default: >>>> + pkts = -1; >>>> + } >>>> + unlock_entry(pktio_entry); >>>> + >>>> + return pkts; >>>> +} >>>> + >>>> +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue) >>>> +{ >>>> + pktio_entry_t *pktio_entry = get_entry(id); >>>> + queue_entry_t *qentry = queue_to_qentry(queue); >>>> + >>>> + if (pktio_entry == NULL || qentry == NULL) >>>> + return -1; >>>> + >>>> + if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN) >>>> + return -1; >>>> + >>>> + lock_entry(pktio_entry); >>>> + pktio_entry->s.inq_default = queue; >>>> + unlock_entry(pktio_entry); >>>> + >>>> + queue_lock(qentry); >>>> + qentry->s.pktin = id; >>>> + qentry->s.status = QUEUE_STATUS_SCHED; >>>> + queue_unlock(qentry); >>>> + >>>> + odp_schedule_queue(queue, qentry->s.param.sched.prio); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +int odp_pktio_inq_remdef(odp_pktio_t id) >>>> +{ >>>> + return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID); >>>> +} >>>> + >>>> +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id) >>>> +{ >>>> + pktio_entry_t *pktio_entry = get_entry(id); >>>> + >>>> + if (pktio_entry == NULL) >>>> + return ODP_QUEUE_INVALID; >>>> + >>>> + return pktio_entry->s.inq_default; >>>> +} >>>> + >>>> +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id) >>>> +{ >>>> + pktio_entry_t *pktio_entry = get_entry(id); >>>> + >>>> + if (pktio_entry == NULL) >>>> + return ODP_QUEUE_INVALID; >>>> + >>>> + return pktio_entry->s.outq_default; >>>> +} >>>> + >>>> +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) >>>> +{ >>>> + odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t) >>>> buf_hdr); >>>> + int len = 1; >>>> + int nbr; >>>> + >>>> + nbr = odp_pktio_send(qentry->s.pktout, &pkt, len); >>>> + return (nbr == len ? 0 : -1); >>>> +} >>>> + >>>> +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry) >>>> +{ >>>> + (void)qentry; >>>> + return NULL; >>>> +} >>>> + >>>> +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t >>>> *buf_hdr[], >>>> + int num) >>>> +{ >>>> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >>>> + int nbr; >>>> + int i; >>>> + >>>> + for (i = 0; i < num; ++i) >>>> + pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t) >>>> buf_hdr[i]); >>>> + >>>> + nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num); >>>> + return (nbr == num ? 0 : -1); >>>> +} >>>> + >>>> +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t >>>> *buf_hdr[], >>>> + int num) >>>> +{ >>>> + (void)qentry; >>>> + (void)buf_hdr; >>>> + (void)num; >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) >>>> +{ >>>> + /* Use default action */ >>>> + return queue_enq(qentry, buf_hdr); >>>> +} >>>> + >>>> +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry) >>>> +{ >>>> + odp_buffer_hdr_t *buf_hdr; >>>> + >>>> + buf_hdr = queue_deq(qentry); >>>> + >>>> + if (buf_hdr == NULL) { >>>> + odp_packet_t pkt; >>>> + odp_buffer_t buf; >>>> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >>>> + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; >>>> + int pkts, i, j; >>>> + >>>> + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, >>>> + QUEUE_MULTI_MAX); >>>> + >>>> + if (pkts > 0) { >>>> + pkt = pkt_tbl[0]; >>>> + buf = odp_buffer_from_packet(pkt); >>>> + buf_hdr = odp_buf_to_hdr(buf); >>>> + >>>> + for (i = 1, j = 0; i < pkts; ++i) { >>>> + buf = >>>> odp_buffer_from_packet(pkt_tbl[i]); >>>> + tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf); >>>> + } >>>> + queue_enq_multi(qentry, tmp_hdr_tbl, j); >>>> + } >>>> + } >>>> + >>>> + return buf_hdr; >>>> +} >>>> + >>>> +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t >>>> *buf_hdr[], int num) >>>> +{ >>>> + /* Use default action */ >>>> + return queue_enq_multi(qentry, buf_hdr, num); >>>> +} >>>> + >>>> +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t >>>> *buf_hdr[], int num) >>>> +{ >>>> + int nbr; >>>> + >>>> + nbr = queue_deq_multi(qentry, buf_hdr, num); >>>> + >>>> + if (nbr < num) { >>>> + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; >>>> + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; >>>> + odp_buffer_t buf; >>>> + int pkts, i; >>>> + >>>> + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, >>>> + QUEUE_MULTI_MAX); >>>> + if (pkts > 0) { >>>> + for (i = 0; i < pkts; ++i) { >>>> + buf = >>>> odp_buffer_from_packet(pkt_tbl[i]); >>>> + tmp_hdr_tbl[i] = odp_buf_to_hdr(buf); >>>> + } >>>> + queue_enq_multi(qentry, tmp_hdr_tbl, pkts); >>>> + } >>>> + } >>>> + >>>> + return nbr; >>>> +} >>>> diff --git a/platform/linux-dpdk/source/odp_queue.c >>>> b/platform/linux-dpdk/source/odp_queue.c >>>> new file mode 100644 >>>> index 0000000..554b8ea >>>> --- /dev/null >>>> +++ b/platform/linux-dpdk/source/odp_queue.c >>>> @@ -0,0 +1,435 @@ >>>> +/* Copyright (c) 2013, Linaro Limited >>>> + * All rights reserved. >>>> + * >>>> + * SPDX-License-Identifier: BSD-3-Clause >>>> + */ >>>> + >>>> +#include <odp_queue.h> >>>> +#include <odp_queue_internal.h> >>>> +#include <odp_std_types.h> >>>> +#include <odp_align.h> >>>> +#include <odp_buffer.h> >>>> +#include <odp_buffer_internal.h> >>>> +#include <odp_buffer_pool_internal.h> >>>> +#include <odp_internal.h> >>>> +#include <odp_shared_memory.h> >>>> +#include <odp_schedule_internal.h> >>>> +#include <odp_config.h> >>>> +#include <odp_packet_io_internal.h> >>>> +#include <odp_packet_io_queue.h> >>>> +#include <odp_debug.h> >>>> +#include <odp_hints.h> >>>> + >>>> +#ifdef USE_TICKETLOCK >>>> +#include <odp_ticketlock.h> >>>> +#define LOCK(a) odp_ticketlock_lock(a) >>>> +#define UNLOCK(a) odp_ticketlock_unlock(a) >>>> +#define LOCK_INIT(a) odp_ticketlock_init(a) >>>> +#else >>>> +#include <odp_spinlock.h> >>>> +#define LOCK(a) odp_spinlock_lock(a) >>>> +#define UNLOCK(a) odp_spinlock_unlock(a) >>>> +#define LOCK_INIT(a) odp_spinlock_init(a) >>>> +#endif >>>> + >>>> +#include <string.h> >>>> + >>>> + >>>> +typedef struct queue_table_t { >>>> + queue_entry_t queue[ODP_CONFIG_QUEUES]; >>>> +} queue_table_t; >>>> + >>>> +static queue_table_t *queue_tbl; >>>> + >>>> + >>>> +queue_entry_t *get_qentry(uint32_t queue_id) >>>> +{ >>>> + return &queue_tbl->queue[queue_id]; >>>> +} >>>> + >>>> +static void queue_init(queue_entry_t *queue, const char *name, >>>> + odp_queue_type_t type, odp_queue_param_t *param) >>>> +{ >>>> + strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1); >>>> + queue->s.type = type; >>>> + >>>> + if (param) { >>>> + memcpy(&queue->s.param, param, >>>> sizeof(odp_queue_param_t)); >>>> + } else { >>>> + /* Defaults */ >>>> + memset(&queue->s.param, 0, sizeof(odp_queue_param_t)); >>>> + queue->s.param.sched.prio = ODP_SCHED_PRIO_DEFAULT; >>>> + queue->s.param.sched.sync = ODP_SCHED_SYNC_DEFAULT; >>>> + queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT; >>>> + } >>>> + >>>> + switch (type) { >>>> + case ODP_QUEUE_TYPE_PKTIN: >>>> + queue->s.enqueue = pktin_enqueue; >>>> + queue->s.dequeue = pktin_dequeue; >>>> + queue->s.enqueue_multi = pktin_enq_multi; >>>> + queue->s.dequeue_multi = pktin_deq_multi; >>>> + break; >>>> + case ODP_QUEUE_TYPE_PKTOUT: >>>> + queue->s.enqueue = pktout_enqueue; >>>> + queue->s.dequeue = pktout_dequeue; >>>> + queue->s.enqueue_multi = pktout_enq_multi; >>>> + queue->s.dequeue_multi = pktout_deq_multi; >>>> + break; >>>> + default: >>>> + queue->s.enqueue = queue_enq; >>>> + queue->s.dequeue = queue_deq; >>>> + queue->s.enqueue_multi = queue_enq_multi; >>>> + queue->s.dequeue_multi = queue_deq_multi; >>>> + break; >>>> + } >>>> + >>>> + queue->s.head = NULL; >>>> + queue->s.tail = NULL; >>>> + queue->s.sched_buf = ODP_BUFFER_INVALID; >>>> +} >>>> + >>>> + >>>> +int odp_queue_init_global(void) >>>> +{ >>>> + uint32_t i; >>>> + >>>> + ODP_DBG("Queue init ... "); >>>> + >>>> + queue_tbl = odp_shm_reserve("odp_queues", >>>> + sizeof(queue_table_t), >>>> + sizeof(queue_entry_t)); >>>> + >>>> + if (queue_tbl == NULL) >>>> + return -1; >>>> + >>>> + memset(queue_tbl, 0, sizeof(queue_table_t)); >>>> + >>>> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >>>> + /* init locks */ >>>> + queue_entry_t *queue = get_qentry(i); >>>> + LOCK_INIT(&queue->s.lock); >>>> + queue->s.handle = queue_from_id(i); >>>> + } >>>> + >>>> + ODP_DBG("done\n"); >>>> + ODP_DBG("Queue init global\n"); >>>> + ODP_DBG(" struct queue_entry_s size %zu\n", >>>> + sizeof(struct queue_entry_s)); >>>> + ODP_DBG(" queue_entry_t size %zu\n", >>>> + sizeof(queue_entry_t)); >>>> + ODP_DBG("\n"); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> +odp_queue_type_t odp_queue_type(odp_queue_t handle) >>>> +{ >>>> + queue_entry_t *queue; >>>> + >>>> + queue = queue_to_qentry(handle); >>>> + >>>> + return queue->s.type; >>>> +} >>>> + >>>> +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle) >>>> +{ >>>> + queue_entry_t *queue; >>>> + >>>> + queue = queue_to_qentry(handle); >>>> + >>>> + return queue->s.param.sched.sync; >>>> +} >>>> + >>>> +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type, >>>> + odp_queue_param_t *param) >>>> +{ >>>> + uint32_t i; >>>> + queue_entry_t *queue; >>>> + odp_queue_t handle = ODP_QUEUE_INVALID; >>>> + >>>> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >>>> + queue = &queue_tbl->queue[i]; >>>> + >>>> + if (queue->s.status != QUEUE_STATUS_FREE) >>>> + continue; >>>> + >>>> + LOCK(&queue->s.lock); >>>> + if (queue->s.status == QUEUE_STATUS_FREE) { >>>> + queue_init(queue, name, type, param); >>>> + >>>> + if (type == ODP_QUEUE_TYPE_SCHED || >>>> + type == ODP_QUEUE_TYPE_PKTIN) >>>> + queue->s.status = QUEUE_STATUS_NOTSCHED; >>>> + else >>>> + queue->s.status = QUEUE_STATUS_READY; >>>> + >>>> + handle = queue->s.handle; >>>> + UNLOCK(&queue->s.lock); >>>> + break; >>>> + } >>>> + UNLOCK(&queue->s.lock); >>>> + } >>>> + >>>> + if (handle != ODP_QUEUE_INVALID && >>>> + (type == ODP_QUEUE_TYPE_SCHED || type == >>>> ODP_QUEUE_TYPE_PKTIN)) { >>>> + odp_buffer_t buf; >>>> + >>>> + buf = odp_schedule_buffer_alloc(handle); >>>> + if (buf == ODP_BUFFER_INVALID) { >>>> + ODP_ERR("queue_init: sched buf alloc failed\n"); >>>> + return ODP_QUEUE_INVALID; >>>> + } >>>> + >>>> + queue->s.sched_buf = buf; >>>> + odp_schedule_mask_set(handle, >>>> queue->s.param.sched.prio); >>>> + } >>>> + >>>> + return handle; >>>> +} >>>> + >>>> + >>>> +odp_buffer_t queue_sched_buf(odp_queue_t handle) >>>> +{ >>>> + queue_entry_t *queue; >>>> + queue = queue_to_qentry(handle); >>>> + >>>> + return queue->s.sched_buf; >>>> +} >>>> + >>>> + >>>> +int queue_sched_atomic(odp_queue_t handle) >>>> +{ >>>> + queue_entry_t *queue; >>>> + queue = queue_to_qentry(handle); >>>> + >>>> + return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC; >>>> +} >>>> + >>>> + >>>> +odp_queue_t odp_queue_lookup(const char *name) >>>> +{ >>>> + uint32_t i; >>>> + >>>> + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { >>>> + queue_entry_t *queue = &queue_tbl->queue[i]; >>>> + >>>> + if (queue->s.status == QUEUE_STATUS_FREE) >>>> + continue; >>>> + >>>> + LOCK(&queue->s.lock); >>>> + if (strcmp(name, queue->s.name) == 0) { >>>> + /* found it */ >>>> + UNLOCK(&queue->s.lock); >>>> + return queue->s.handle; >>>> + } >>>> + UNLOCK(&queue->s.lock); >>>> + } >>>> + >>>> + return ODP_QUEUE_INVALID; >>>> +} >>>> + >>>> + >>>> +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr) >>>> +{ >>>> + int sched = 0; >>>> + >>>> + LOCK(&queue->s.lock); >>>> + if (queue->s.head == NULL) { >>>> + /* Empty queue */ >>>> + queue->s.head = buf_hdr; >>>> + queue->s.tail = buf_hdr; >>>> + buf_hdr->pkt.next = NULL; >>>> + } else { >>>> + queue->s.tail->pkt.next = buf_hdr; >>>> + queue->s.tail = buf_hdr; >>>> + buf_hdr->pkt.next = NULL; >>>> + } >>>> + >>>> + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { >>>> + queue->s.status = QUEUE_STATUS_SCHED; >>>> + sched = 1; /* retval: schedule queue */ >>>> + } >>>> + UNLOCK(&queue->s.lock); >>>> + >>>> + /* Add queue to scheduling */ >>>> + if (sched == 1) >>>> + odp_schedule_queue(queue->s.handle, >>>> queue->s.param.sched.prio); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> + >>>> +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], >>>> int num) >>>> +{ >>>> + int sched = 0; >>>> + int i; >>>> + odp_buffer_hdr_t *tail; >>>> + >>>> + for (i = 0; i < num - 1; i++) >>>> + buf_hdr[i]->pkt.next = buf_hdr[i+1]; >>>> + >>>> + tail = buf_hdr[num-1]; >>>> + buf_hdr[num-1]->pkt.next = NULL; >>>> + >>>> + LOCK(&queue->s.lock); >>>> + /* Empty queue */ >>>> + if (queue->s.head == NULL) >>>> + queue->s.head = buf_hdr[0]; >>>> + else >>>> + queue->s.tail->pkt.next = buf_hdr[0]; >>>> + >>>> + queue->s.tail = tail; >>>> + >>>> + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { >>>> + queue->s.status = QUEUE_STATUS_SCHED; >>>> + sched = 1; /* retval: schedule queue */ >>>> + } >>>> + UNLOCK(&queue->s.lock); >>>> + >>>> + /* Add queue to scheduling */ >>>> + if (sched == 1) >>>> + odp_schedule_queue(queue->s.handle, >>>> queue->s.param.sched.prio); >>>> + >>>> + return 0; >>>> +} >>>> + >>>> + >>>> +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int >>>> num) >>>> +{ >>>> + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; >>>> + queue_entry_t *queue; >>>> + int i; >>>> + >>>> + if (num > QUEUE_MULTI_MAX) >>>> + num = QUEUE_MULTI_MAX; >>>> + >>>> + queue = queue_to_qentry(handle); >>>> + >>>> + for (i = 0; i < num; i++) >>>> + buf_hdr[i] = odp_buf_to_hdr(buf[i]); >>>> + >>>> + return queue->s.enqueue_multi(queue, buf_hdr, num); >>>> +} >>>> + >>>> + >>>> +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf) >>>> +{ >>>> + odp_buffer_hdr_t *buf_hdr; >>>> + queue_entry_t *queue; >>>> + >>>> + queue = queue_to_qentry(handle); >>>> + buf_hdr = odp_buf_to_hdr(buf); >>>> + >>>> + return queue->s.enqueue(queue, buf_hdr); >>>> +} >>>> + >>>> + >>>> +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue) >>>> +{ >>>> + odp_buffer_hdr_t *buf_hdr = NULL; >>>> + >>>> + LOCK(&queue->s.lock); >>>> + >>>> + if (queue->s.head == NULL) { >>>> + /* Already empty queue */ >>>> + if (queue->s.status == QUEUE_STATUS_SCHED && >>>> + queue->s.type != ODP_QUEUE_TYPE_PKTIN) >>>> + queue->s.status = QUEUE_STATUS_NOTSCHED; >>>> + } else { >>>> + buf_hdr = queue->s.head; >>>> + queue->s.head = buf_hdr->pkt.next; >>>> + buf_hdr->pkt.next = NULL; >>>> + >>>> + if (queue->s.head == NULL) { >>>> + /* Queue is now empty */ >>>> + queue->s.tail = NULL; >>>> + } >>>> + } >>>> + >>>> + UNLOCK(&queue->s.lock); >>>> + >>>> + return buf_hdr; >>>> +} >>>> + >>>> + >>>> +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], >>>> int num) >>>> +{ >>>> + int i = 0; >>>> + >>>> + LOCK(&queue->s.lock); >>>> + >>>> + if (queue->s.head == NULL) { >>>> + /* Already empty queue */ >>>> + if (queue->s.status == QUEUE_STATUS_SCHED && >>>> + queue->s.type != ODP_QUEUE_TYPE_PKTIN) >>>> + queue->s.status = QUEUE_STATUS_NOTSCHED; >>>> + } else { >>>> + odp_buffer_hdr_t *hdr = queue->s.head; >>>> + >>>> + for (; i < num && hdr; i++) { >>>> + buf_hdr[i] = hdr; >>>> + /* odp_prefetch(hdr->addr); */ >>>> + hdr = hdr->pkt.next; >>>> + buf_hdr[i]->pkt.next = NULL; >>>> + } >>>> + >>>> + queue->s.head = hdr; >>>> + >>>> + if (hdr == NULL) { >>>> + /* Queue is now empty */ >>>> + queue->s.tail = NULL; >>>> + } >>>> + } >>>> + >>>> + UNLOCK(&queue->s.lock); >>>> + >>>> + return i; >>>> +} >>>> + >>>> + >>>> +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int >>>> num) >>>> +{ >>>> + queue_entry_t *queue; >>>> + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; >>>> + int i, ret; >>>> + >>>> + if (num > QUEUE_MULTI_MAX) >>>> + num = QUEUE_MULTI_MAX; >>>> + >>>> + queue = queue_to_qentry(handle); >>>> + >>>> + ret = queue->s.dequeue_multi(queue, buf_hdr, num); >>>> + >>>> + for (i = 0; i < ret; i++) >>>> + buf[i] = (odp_buffer_t) buf_hdr[i]; >>>> + >>>> + return ret; >>>> +} >>>> + >>>> + >>>> +odp_buffer_t odp_queue_deq(odp_queue_t handle) >>>> +{ >>>> + queue_entry_t *queue; >>>> + odp_buffer_hdr_t *buf_hdr; >>>> + >>>> + queue = queue_to_qentry(handle); >>>> + buf_hdr = queue->s.dequeue(queue); >>>> + >>>> + if (buf_hdr) >>>> + return (odp_buffer_t) buf_hdr; >>>> + >>>> + return ODP_BUFFER_INVALID; >>>> +} >>>> + >>>> + >>>> +void queue_lock(queue_entry_t *queue) >>>> +{ >>>> + LOCK(&queue->s.lock); >>>> +} >>>> + >>>> + >>>> +void queue_unlock(queue_entry_t *queue) >>>> +{ >>>> + UNLOCK(&queue->s.lock); >>>> +} >>>> -- >>>> 1.9.1 >>>> >>>> >>>> _______________________________________________ >>>> lng-odp mailing list >>>> lng-odp@lists.linaro.org >>>> http://lists.linaro.org/mailman/listinfo/lng-odp >>>> >>> >>> >>> >>> -- >>> *Mike Holmes* >>> Linaro Technical Manager / Lead >>> LNG - ODP >>> >> >> > > > -- > *Mike Holmes* > Linaro Technical Manager / Lead > LNG - ODP >
diff --git a/platform/linux-dpdk/Makefile b/platform/linux-dpdk/Makefile new file mode 100644 index 0000000..bf8d0b3 --- /dev/null +++ b/platform/linux-dpdk/Makefile @@ -0,0 +1,158 @@ +## Copyright (c) 2013, Linaro Limited +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are met: +## +## * Redistributions of source code must retain the above copyright notice, this +## list of conditions and the following disclaimer. +## +## * Redistributions in binary form must reproduce the above copyright notice, this +## list of conditions and the following disclaimer in the documentation and/or +## other materials provided with the distribution. +## +## * Neither the name of Linaro Limited nor the names of its contributors may be +## used to endorse or promote products derived from this software without specific +## prior written permission. +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +## SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +## CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +.DEFAULT_GOAL := libs + +ODP_ROOT = ../.. +LIB_DIR = ./lib +DOC_DIR = ./doc + +LINUX_GENERIC_DIR = ../linux-generic + +RTE_SDK ?= $(abspath $(ODP_ROOT)/../dpdk) +RTE_OUTPUT ?= $(abspath $(RTE_SDK)/build) +RTE_LIB ?= $(abspath $(RTE_OUTPUT)/lib/libintel_dpdk.a) + +PLAT_CFLAGS = -include $(RTE_OUTPUT)/include/rte_config.h +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/arch +PLAT_CFLAGS += -I$(RTE_OUTPUT)/include/exec-env +PLAT_CFLAGS += -msse4.2 + +EXTRA_CFLAGS += $(PLAT_CFLAGS) +EXTRA_CFLAGS += -I./include +EXTRA_CFLAGS += -I./include/api +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include +EXTRA_CFLAGS += -I$(LINUX_GENERIC_DIR)/include/api +EXTRA_CFLAGS += -I$(ODP_ROOT)/include + +include $(ODP_ROOT)/Makefile.inc +STATIC_LIB = ./lib/libodp.a + +# +# Object files +# +OBJS = +OBJS += $(OBJ_DIR)/odp_barrier.o +OBJS += $(OBJ_DIR)/odp_buffer.o +OBJS += $(OBJ_DIR)/odp_buffer_pool.o +OBJS += $(OBJ_DIR)/odp_coremask.o +OBJS += $(OBJ_DIR)/odp_init.o +OBJS += $(OBJ_DIR)/odp_linux.o +OBJS += $(OBJ_DIR)/odp_packet.o +OBJS += $(OBJ_DIR)/odp_packet_flags.o +OBJS += $(OBJ_DIR)/odp_packet_io.o +OBJS += $(OBJ_DIR)/odp_packet_socket.o +OBJS += $(OBJ_DIR)/odp_queue.o +OBJS += $(OBJ_DIR)/odp_schedule.o +OBJS += $(OBJ_DIR)/odp_shared_memory.o +OBJS += $(OBJ_DIR)/odp_spinlock.o +OBJS += $(OBJ_DIR)/odp_system_info.o +OBJS += $(OBJ_DIR)/odp_thread.o +OBJS += $(OBJ_DIR)/odp_ticketlock.o +OBJS += $(OBJ_DIR)/odp_time.o +OBJS += $(OBJ_DIR)/odp_timer.o +OBJS += $(OBJ_DIR)/odp_ring.o +OBJS += $(OBJ_DIR)/odp_rwlock.o +OBJS += $(OBJ_DIR)/odp_packet_dpdk.o + +DEPS = $(OBJS:.o=.d) + +.PHONY: all +all: libs docs + +-include $(DEPS) + +#$(OBJ_DIR): +# $(MKDIR) $(OBJ_DIR) + +$(LIB_DIR): + $(MKDIR) $(LIB_DIR) + +$(DOC_DIR): + $(MKDIR) $(DOC_DIR)/html + $(MKDIR) $(DOC_DIR)/latex + +# +# Compile rules +# +vpath %.c source:$(LINUX_GENERIC_DIR)/source + +$(OBJ_DIR)/%.o: %.c + $(ECHO) " CC $<" + $(CC) -c -MD $(EXTRA_CFLAGS) $(CFLAGS) -o $@ $< + +# +# Lib rule +# +$(OBJ_DIR)/libodp.o: $(OBJS) + $(ECHO) " LD $@" + $(LD) -r -o $@ $(OBJS) $(RTE_LIB) + +$(STATIC_LIB): $(OBJ_DIR)/libodp.o + $(ECHO) " AR $@" + $(AR) -cr $@ $(OBJ_DIR)/libodp.o + + +clean: + $(RMDIR) $(OBJ_DIR) + $(RMDIR) $(LIB_DIR) + $(RMDIR) $(DOC_DIR) + $(RM) Doxyfile + +Doxyfile: Doxyfile.in + doxygen -u - < $< > $@ + +.PHONY: docs +docs: $(DOC_DIR) Doxyfile ./include/odp*.h + doxygen + +.PHONY: docs_install +docs_install: docs + $(COPY) doc $(DESTDIR) + +.PHONY: pdf +pdf: docs + make --directory doc/latex refman.pdf 1> /dev/null + +.PHONY: libs +libs: $(OBJ_DIR) $(LIB_DIR) $(STATIC_LIB) + +.PHONY: lib_install +lib_install: libs + install -d $(DESTDIR)/lib + install -m 0644 ${STATIC_LIB} $(DESTDIR)/lib/ + +.PHONY: headers_install +headers_install: libs + $(ECHO) Installing headers to $(DESTDIR)/include + $(COPY) $(ODP_ROOT)/include $(DESTDIR) + $(COPY) $(LINUX_GENERIC_DIR)/include/api/* $(DESTDIR)/include/ + $(COPY) include/api/* $(DESTDIR)/include/ + +install: lib_install headers_install diff --git a/platform/linux-dpdk/Makefile.inc b/platform/linux-dpdk/Makefile.inc new file mode 100644 index 0000000..fe7679b --- /dev/null +++ b/platform/linux-dpdk/Makefile.inc @@ -0,0 +1,7 @@ +# Copyright (c) 2013, Linaro Limited +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +STD_LIBS += -ldl + diff --git a/platform/linux-dpdk/include/api/odp_buffer.h b/platform/linux-dpdk/include/api/odp_buffer.h new file mode 100644 index 0000000..286d9e6 --- /dev/null +++ b/platform/linux-dpdk/include/api/odp_buffer.h @@ -0,0 +1,101 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP buffer descriptor + */ + +#ifndef ODP_BUFFER_H_ +#define ODP_BUFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +#include <odp_std_types.h> + + + + + +/** + * ODP buffer + */ +typedef unsigned long odp_buffer_t; + + +#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */ + + +/** + * Buffer start address + * + * @param buf Buffer handle + * + * @return Buffer start address + */ +void *odp_buffer_addr(odp_buffer_t buf); + +/** + * Buffer maximum data size + * + * @param buf Buffer handle + * + * @return Buffer maximum data size + */ +size_t odp_buffer_size(odp_buffer_t buf); + +/** + * Buffer type + * + * @param buf Buffer handle + * + * @return Buffer type + */ +int odp_buffer_type(odp_buffer_t buf); + +#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */ +#define ODP_BUFFER_TYPE_RAW 0 /**< Raw buffer */ +#define ODP_BUFFER_TYPE_PACKET 1 /**< Packet buffer */ +#define ODP_BUFFER_TYPE_TIMER 2 /**< Timer buffer */ + +/** + * Tests if buffer is part of a scatter/gather list + * + * @param buf Buffer handle + * + * @return 1 if belongs to a scatter list, otherwise 0 + */ +int odp_buffer_is_scatter(odp_buffer_t buf); + +/** + * Tests if buffer is valid + * + * @param buf Buffer handle + * + * @return 1 if valid, otherwise 0 + */ +int odp_buffer_is_valid(odp_buffer_t buf); + +/** + * Print buffer metadata to STDOUT + * + * @param buf Buffer handle + * + */ +void odp_buffer_print(odp_buffer_t buf); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-dpdk/include/api/odp_buffer_pool.h b/platform/linux-dpdk/include/api/odp_buffer_pool.h new file mode 100644 index 0000000..4b75cf5 --- /dev/null +++ b/platform/linux-dpdk/include/api/odp_buffer_pool.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP buffer pool + */ + +#ifndef ODP_BUFFER_POOL_H_ +#define ODP_BUFFER_POOL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +#include <odp_std_types.h> +#include <odp_buffer.h> + +/** Maximum queue name lenght in chars */ +#define ODP_BUFFER_POOL_NAME_LEN 32 + +/** Invalid buffer pool */ +#define ODP_BUFFER_POOL_INVALID (0xffffffff) + +/** ODP buffer pool */ +typedef unsigned long odp_buffer_pool_t; + + +/** + * Create a buffer pool + * + * @param name Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1 chars) + * @param base_addr Pool base address + * @param size Pool size in bytes + * @param buf_size Buffer size in bytes + * @param buf_align Minimum buffer alignment + * @param buf_type Buffer type + * + * @return Buffer pool handle + */ +odp_buffer_pool_t odp_buffer_pool_create(const char *name, + void *base_addr, uint64_t size, + size_t buf_size, size_t buf_align, + int buf_type); + + +/** + * Find a buffer pool by name + * + * @param name Name of the pool + * + * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found. + */ +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name); + + +/** + * Print buffer pool info + * + * @param pool Pool handle + * + */ +void odp_buffer_pool_print(odp_buffer_pool_t pool); + + + +/** + * Buffer alloc + * + * @param pool Pool handle + * + * @return Buffer handle or ODP_BUFFER_INVALID + */ +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool); + + +/** + * Buffer free + * + * @param buf Buffer handle + * + */ +void odp_buffer_free(odp_buffer_t buf); + + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-dpdk/include/api/odp_packet.h b/platform/linux-dpdk/include/api/odp_packet.h new file mode 100644 index 0000000..bdb3417 --- /dev/null +++ b/platform/linux-dpdk/include/api/odp_packet.h @@ -0,0 +1,228 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP packet descriptor + */ + +#ifndef ODP_PACKET_H_ +#define ODP_PACKET_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp_buffer.h> + + +/** + * ODP packet descriptor + */ +typedef unsigned long odp_packet_t; + + +/** Invalid packet */ +#define ODP_PACKET_INVALID ODP_BUFFER_INVALID + +/** Invalid offset */ +#define ODP_PACKET_OFFSET_INVALID ((size_t)-1) + + +/** + * Initialize the packet + * + * Needs to be called if the user allocates a packet buffer, i.e. the packet + * has not been received from I/O through ODP. + * + * @param pkt Packet handle + */ +void odp_packet_init(odp_packet_t pkt); + +/** + * Convert from packet handle to buffer handle + * + * @param buf Buffer handle + * + * @return Packet handle + */ +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf); + +/** + * Convert from buffer handle to packet handle + * + * @param pkt Packet handle + * + * @return Buffer handle + */ +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt); + +/** + * Set the packet length + * + * @param pkt Packet handle + * @param len Length of packet in bytes + */ +void odp_packet_set_len(odp_packet_t pkt, size_t len); + +/** + * Get the packet length + * + * @param pkt Packet handle + * + * @return Packet length in bytes + */ +size_t odp_packet_get_len(odp_packet_t pkt); + +/** + * Get address to the start of the packet buffer + * + * The address of the packet buffer is not necessarily the same as the start + * address of the received frame, e.g. an eth frame may be offset by 2 or 6 + * bytes to ensure 32 or 64-bit alignment of the IP header. + * Use odp_packet_l2(pkt) to get the start address of a received valid frame + * or odp_packet_start(pkt) to get the start address even if no valid L2 header + * could be found. + * + * @param pkt Packet handle + * + * @return Pointer to the start of the packet buffer + * + * @see odp_packet_l2(), odp_packet_start() + */ +uint8_t *odp_packet_buf_addr(odp_packet_t pkt); + +/** + * Get pointer to the start of the received frame + * + * The address of the packet buffer is not necessarily the same as the start + * address of the received frame, e.g. an eth frame may be offset by 2 or 6 + * bytes to ensure 32 or 64-bit alignment of the IP header. + * Use odp_packet_l2(pkt) to get the start address of a received valid eth frame + * + * odp_packet_start() will always return a pointer to the start of the frame, + * even if the frame is unrecognized and no valid L2 header could be found. + * + * @param pkt Packet handle + * + * @return Pointer to the start of the received frame + * + * @see odp_packet_l2(), odp_packet_buf_addr() + */ +uint8_t *odp_packet_start(odp_packet_t pkt); + +/** + * Get pointer to the start of the L2 frame + * + * The L2 frame header address is not necessarily the same as the address of the + * packet buffer, see odp_packet_buf_addr() + * + * @param pkt Packet handle + * + * @return Pointer to L2 header or NULL if not found + * + * @see odp_packet_buf_addr(), odp_packet_start() + */ +uint8_t *odp_packet_l2(odp_packet_t pkt); + +/** + * Return the byte offset from the packet buffer to the L2 frame + * + * @param pkt Packet handle + * + * @return L2 byte offset or ODP_PACKET_OFFSET_INVALID if not found + */ +size_t odp_packet_l2_offset(odp_packet_t pkt); + +/** + * Set the byte offset to the L2 frame + * + * @param pkt Packet handle + * @param offset L2 byte offset + */ +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset); + + +/** + * Get pointer to the start of the L3 packet + * + * @param pkt Packet handle + * + * @return Pointer to L3 packet or NULL if not found + * + */ +uint8_t *odp_packet_l3(odp_packet_t pkt); + +/** + * Return the byte offset from the packet buffer to the L3 packet + * + * @param pkt Packet handle + * + * @return L3 byte offset or ODP_PACKET_OFFSET_INVALID if not found + */ +size_t odp_packet_l3_offset(odp_packet_t pkt); + +/** + * Set the byte offset to the L3 packet + * + * @param pkt Packet handle + * @param offset L3 byte offset + */ +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset); + + +/** + * Get pointer to the start of the L4 packet + * + * @param pkt Packet handle + * + * @return Pointer to L4 packet or NULL if not found + * + */ +uint8_t *odp_packet_l4(odp_packet_t pkt); + +/** + * Return the byte offset from the packet buffer to the L4 packet + * + * @param pkt Packet handle + * + * @return L4 byte offset or ODP_PACKET_OFFSET_INVALID if not found + */ +size_t odp_packet_l4_offset(odp_packet_t pkt); + +/** + * Set the byte offset to the L4 packet + * + * @param pkt Packet handle + * @param offset L4 byte offset + */ +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset); + +/** + * Print (debug) information about the packet + * + * @param pkt Packet handle + */ +void odp_packet_print(odp_packet_t pkt); + +/** + * Copy contents and metadata from pkt_src to pkt_dst + * Useful when creating copies of packets + * + * @param pkt_dst Destination packet + * @param pkt_src Source packet + * + * @return 0 if successful + */ +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-dpdk/include/api/odp_pktio_types.h b/platform/linux-dpdk/include/api/odp_pktio_types.h new file mode 100644 index 0000000..b23e6da --- /dev/null +++ b/platform/linux-dpdk/include/api/odp_pktio_types.h @@ -0,0 +1,45 @@ + +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_PKTIO_TYPES_H +#define ODP_PKTIO_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* We should ensure that future enum values will never overlap, otherwise + * applications that want netmap suport might get in trouble if the odp lib + * was not built with netmap support and there are more types define below + */ + +typedef enum { + ODP_PKTIO_TYPE_SOCKET_BASIC = 0x1, + ODP_PKTIO_TYPE_SOCKET_MMSG, + ODP_PKTIO_TYPE_SOCKET_MMAP, + ODP_PKTIO_TYPE_NETMAP, + ODP_PKTIO_TYPE_DPDK, +} odp_pktio_type_t; + +#include <odp_pktio_socket.h> +#ifdef ODP_HAVE_NETMAP +#include <odp_pktio_netmap.h> +#endif + +typedef union odp_pktio_params_t { + odp_pktio_type_t type; + socket_params_t sock_params; +#ifdef ODP_HAVE_NETMAP + netmap_params_t nm_params; +#endif +} odp_pktio_params_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h b/platform/linux-dpdk/include/odp_buffer_internal.h new file mode 100644 index 0000000..a47107c --- /dev/null +++ b/platform/linux-dpdk/include/odp_buffer_internal.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP buffer descriptor - implementation internal + */ + +#ifndef ODP_BUFFER_INTERNAL_H_ +#define ODP_BUFFER_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp_std_types.h> +#include <odp_atomic.h> +#include <odp_buffer_pool.h> +#include <odp_buffer.h> +#include <odp_debug.h> +#include <odp_align.h> +#include <rte_mbuf.h> + +/* TODO: move these to correct files */ + +typedef uint64_t odp_phys_addr_t; + +#define ODP_BUFFER_MAX_INDEX (ODP_BUFFER_MAX_BUFFERS - 2) +#define ODP_BUFFER_INVALID_INDEX (ODP_BUFFER_MAX_BUFFERS - 1) + +#define ODP_BUFS_PER_CHUNK 16 +#define ODP_BUFS_PER_SCATTER 4 + +#define ODP_BUFFER_TYPE_CHUNK 0xffff + + +#define ODP_BUFFER_POOL_BITS 4 +#define ODP_BUFFER_INDEX_BITS (32 - ODP_BUFFER_POOL_BITS) +#define ODP_BUFFER_MAX_POOLS (1 << ODP_BUFFER_POOL_BITS) +#define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS) + +typedef union odp_buffer_bits_t { + uint32_t u32; + odp_buffer_t handle; + + struct { + uint32_t pool:ODP_BUFFER_POOL_BITS; + uint32_t index:ODP_BUFFER_INDEX_BITS; + }; +} odp_buffer_bits_t; + + +/* forward declaration */ +struct odp_buffer_hdr_t; + + +typedef struct rte_mbuf odp_buffer_hdr_t; + + +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf); + + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + + diff --git a/platform/linux-dpdk/include/odp_buffer_pool_internal.h b/platform/linux-dpdk/include/odp_buffer_pool_internal.h new file mode 100644 index 0000000..1a36655 --- /dev/null +++ b/platform/linux-dpdk/include/odp_buffer_pool_internal.h @@ -0,0 +1,90 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP buffer pool - internal header + */ + +#ifndef ODP_BUFFER_POOL_INTERNAL_H_ +#define ODP_BUFFER_POOL_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp_std_types.h> +#include <odp_buffer_pool.h> +#include <odp_buffer_internal.h> +#include <odp_align.h> +#include <odp_hints.h> +#include <odp_config.h> +#include <odp_debug.h> + +/* for DPDK */ +#include <rte_mempool.h> + +/* Use ticketlock instead of spinlock */ +#define POOL_USE_TICKETLOCK + +/* Extra error checks */ +/* #define POOL_ERROR_CHECK */ + + +#ifdef POOL_USE_TICKETLOCK +#include <odp_ticketlock.h> +#else +#include <odp_spinlock.h> +#endif + + +struct pool_entry_s { +#ifdef POOL_USE_TICKETLOCK + odp_ticketlock_t lock ODP_ALIGNED_CACHE; +#else + odp_spinlock_t lock ODP_ALIGNED_CACHE; +#endif + + uint64_t free_bufs; + char name[ODP_BUFFER_POOL_NAME_LEN]; + + + odp_buffer_pool_t pool ODP_ALIGNED_CACHE; + uintptr_t buf_base; + size_t buf_size; + size_t buf_offset; + uint64_t num_bufs; + void *pool_base_addr; + uint64_t pool_size; + size_t payload_size; + size_t payload_align; + int buf_type; + size_t hdr_size; +}; + + +extern void *pool_entry_ptr[]; + + +static inline void *get_pool_entry(odp_buffer_pool_t pool_id) +{ + return pool_entry_ptr[pool_id]; +} + + +static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf) +{ + return (odp_buffer_hdr_t *)buf; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h b/platform/linux-dpdk/include/odp_packet_dpdk.h new file mode 100644 index 0000000..0b3db08 --- /dev/null +++ b/platform/linux-dpdk/include/odp_packet_dpdk.h @@ -0,0 +1,88 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_PACKET_DPDK_H +#define ODP_PACKET_DPDK_H + +#include <stdint.h> +#include <net/if.h> + +#include <helper/odp_eth.h> +#include <helper/odp_packet_helper.h> +#include <odp_align.h> +#include <odp_debug.h> +#include <odp_packet.h> +#include <odp_packet_internal.h> +#include <odp_buffer_pool.h> +#include <odp_buffer_pool_internal.h> +#include <odp_buffer_internal.h> +#include <odp_std_types.h> + +#include <rte_config.h> +#include <rte_memory.h> +#include <rte_memzone.h> +#include <rte_launch.h> +#include <rte_tailq.h> +#include <rte_eal.h> +#include <rte_per_lcore.h> +#include <rte_lcore.h> +#include <rte_branch_prediction.h> +#include <rte_prefetch.h> +#include <rte_cycles.h> +#include <rte_errno.h> +#include <rte_debug.h> +#include <rte_log.h> +#include <rte_byteorder.h> +#include <rte_pci.h> +#include <rte_random.h> +#include <rte_ether.h> +#include <rte_ethdev.h> +#include <rte_hash.h> +#include <rte_jhash.h> +#include <rte_hash_crc.h> + + +#define ODP_DPDK_MODE_HW 0 +#define ODP_DPDK_MODE_SW 1 + +#define DPDK_BLOCKING_IO + +/** Packet socket using dpdk mmaped rings for both Rx and Tx */ +typedef struct { + odp_buffer_pool_t pool; + + /********************************/ + char ifname[32]; + uint8_t portid; + uint16_t queueid; +} pkt_dpdk_t; + +/** + * Configure an interface to work in dpdk mode + */ +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, + odp_buffer_pool_t pool); + +/** + * Switch interface from dpdk mode to normal mode + */ +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk); + +/** + * Receive packets using dpdk + */ +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], + unsigned len); + +/** + * Send packets using dpdk + */ +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], + unsigned len); + +int odp_init_dpdk(void); +#endif + diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h new file mode 100644 index 0000000..d9057a2 --- /dev/null +++ b/platform/linux-dpdk/include/odp_packet_internal.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP packet descriptor - implementation internal + */ + +#ifndef ODP_PACKET_INTERNAL_H_ +#define ODP_PACKET_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp_align.h> +#include <odp_debug.h> +#include <odp_buffer_internal.h> +#include <odp_buffer_pool_internal.h> +#include <odp_packet.h> +#include <odp_packet_io.h> + +/** + * Packet input & protocol flags + */ +typedef union { + /* All input flags */ + uint32_t all; + + struct { + /* Bitfield flags for each protocol */ + uint32_t l2:1; /**< known L2 protocol present */ + uint32_t l3:1; /**< known L3 protocol present */ + uint32_t l4:1; /**< known L4 protocol present */ + + uint32_t eth:1; /**< Ethernet */ + uint32_t jumbo:1; /**< Jumbo frame */ + uint32_t vlan:1; /**< VLAN hdr found */ + uint32_t vlan_qinq:1; /**< Stacked VLAN found, QinQ */ + + uint32_t arp:1; /**< ARP */ + + uint32_t ipv4:1; /**< IPv4 */ + uint32_t ipv6:1; /**< IPv6 */ + uint32_t ipfrag:1; /**< IP fragment */ + uint32_t ipopt:1; /**< IP optional headers */ + uint32_t ipsec:1; /**< IPSec decryption may be needed */ + + uint32_t udp:1; /**< UDP */ + uint32_t tcp:1; /**< TCP */ + uint32_t sctp:1; /**< SCTP */ + uint32_t icmp:1; /**< ICMP */ + }; +} input_flags_t; + +ODP_ASSERT(sizeof(input_flags_t) == sizeof(uint32_t), INPUT_FLAGS_SIZE_ERROR); + +/** + * Packet error flags + */ +typedef union { + /* All error flags */ + uint32_t all; + + struct { + /* Bitfield flags for each detected error */ + uint32_t frame_len:1; /**< Frame length error */ + uint32_t l2_chksum:1; /**< L2 checksum error, checks TBD */ + uint32_t ip_err:1; /**< IP error, checks TBD */ + uint32_t tcp_err:1; /**< TCP error, checks TBD */ + uint32_t udp_err:1; /**< UDP error, checks TBD */ + }; +} error_flags_t; + +ODP_ASSERT(sizeof(error_flags_t) == sizeof(uint32_t), ERROR_FLAGS_SIZE_ERROR); + +/** + * Packet output flags + */ +typedef union { + /* All output flags */ + uint32_t all; + + struct { + /* Bitfield flags for each output option */ + uint32_t l4_chksum:1; /**< Request L4 checksum calculation */ + }; +} output_flags_t; + +ODP_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), OUTPUT_FLAGS_SIZE_ERROR); + +/** + * Internal Packet header + */ +typedef struct { + /* common buffer header */ + odp_buffer_hdr_t buf_hdr; + + input_flags_t input_flags; + error_flags_t error_flags; + output_flags_t output_flags; + + uint32_t frame_offset; /**< offset to start of frame, even on error */ + uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */ + uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */ + uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also ICMP) */ + + uint32_t frame_len; + + odp_pktio_t input; + + uint32_t pad; + uint8_t payload[]; + +} odp_packet_hdr_t; + +/** + * Return the packet header + */ +static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt) +{ + return (odp_packet_hdr_t *)pkt; +} + +/** + * Parse packet and set internal metadata + */ +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t l2_offset); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h b/platform/linux-dpdk/include/odp_packet_io_internal.h new file mode 100644 index 0000000..5948063 --- /dev/null +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP packet IO - implementation internal + */ + +#ifndef ODP_PACKET_IO_INTERNAL_H_ +#define ODP_PACKET_IO_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp_spinlock.h> +#include <odp_packet_socket.h> +#ifdef ODP_HAVE_NETMAP +#include <odp_packet_netmap.h> +#endif +#include <odp_packet_dpdk.h> + +struct pktio_entry { + odp_spinlock_t lock; /**< entry spinlock */ + int taken; /**< is entry taken(1) or free(0) */ + odp_queue_t inq_default; /**< default input queue, if set */ + odp_queue_t outq_default; /**< default out queue */ + odp_pktio_params_t params; /**< pktio parameters */ + pkt_sock_t pkt_sock; /**< using socket API for IO */ + pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap API for IO */ +#ifdef ODP_HAVE_NETMAP + pkt_netmap_t pkt_nm; /**< using netmap API for IO */ +#endif + pkt_dpdk_t pkt_dpdk; /**< using DPDK API for IO */ +}; + +typedef union { + struct pktio_entry s; + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct pktio_entry))]; +} pktio_entry_t; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/platform/linux-dpdk/source/odp_buffer.c b/platform/linux-dpdk/source/odp_buffer.c new file mode 100644 index 0000000..bfb5ff6 --- /dev/null +++ b/platform/linux-dpdk/source/odp_buffer.c @@ -0,0 +1,102 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_buffer.h> +#include <odp_buffer_internal.h> +#include <odp_buffer_pool_internal.h> + +#include <string.h> +#include <stdio.h> + + +void *odp_buffer_addr(odp_buffer_t buf) +{ + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); + + return hdr->buf_addr; +} + + +size_t odp_buffer_size(odp_buffer_t buf) +{ + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); + + return hdr->buf_len; +} + + +int odp_buffer_type(odp_buffer_t buf) +{ + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); + + return hdr->type; +} + + +int odp_buffer_is_scatter(odp_buffer_t buf) +{ + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); + + if (hdr->refcnt == 0) + return 0; + else + return 1; +} + + +int odp_buffer_is_valid(odp_buffer_t buf) +{ + odp_buffer_bits_t handle; + + handle.u32 = buf; + + return (handle.index != ODP_BUFFER_INVALID_INDEX); +} + + +int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf) +{ + odp_buffer_hdr_t *hdr; + int len = 0; + + if (!odp_buffer_is_valid(buf)) { + printf("Buffer is not valid.\n"); + return len; + } + + hdr = odp_buf_to_hdr(buf); + + len += snprintf(&str[len], n-len, + "Buffer\n"); + len += snprintf(&str[len], n-len, + " pool %"PRIu64"\n", (int64_t) hdr->pool); + len += snprintf(&str[len], n-len, + " phy_addr %"PRIu64"\n", hdr->buf_physaddr); + len += snprintf(&str[len], n-len, + " addr %p\n", hdr->buf_addr); + len += snprintf(&str[len], n-len, + " size %u\n", hdr->buf_len); + len += snprintf(&str[len], n-len, + " ref_count %i\n", hdr->refcnt); + len += snprintf(&str[len], n-len, + " type %i\n", hdr->type); + + return len; +} + + +void odp_buffer_print(odp_buffer_t buf) +{ + int max_len = 512; + char str[max_len]; + int len; + + len = odp_buffer_snprint(str, max_len-1, buf); + str[len] = 0; + + printf("\n%s\n", str); +} + diff --git a/platform/linux-dpdk/source/odp_buffer_pool.c b/platform/linux-dpdk/source/odp_buffer_pool.c new file mode 100644 index 0000000..de90275 --- /dev/null +++ b/platform/linux-dpdk/source/odp_buffer_pool.c @@ -0,0 +1,156 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_std_types.h> +#include <odp_buffer_pool.h> +#include <odp_buffer_pool_internal.h> +#include <odp_buffer_internal.h> +#include <odp_packet_internal.h> +#include <odp_shared_memory.h> +#include <odp_align.h> +#include <odp_internal.h> +#include <odp_config.h> +#include <odp_hints.h> +#include <odp_debug.h> + +#include <string.h> +#include <stdlib.h> + +/* for DPDK */ +#include <odp_packet_dpdk.h> + +#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) +#define NB_MBUF 8192 + +#ifdef POOL_USE_TICKETLOCK +#include <odp_ticketlock.h> +#define LOCK(a) odp_ticketlock_lock(a) +#define UNLOCK(a) odp_ticketlock_unlock(a) +#define LOCK_INIT(a) odp_ticketlock_init(a) +#else +#include <odp_spinlock.h> +#define LOCK(a) odp_spinlock_lock(a) +#define UNLOCK(a) odp_spinlock_unlock(a) +#define LOCK_INIT(a) odp_spinlock_init(a) +#endif + + +#if ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS +#error ODP_CONFIG_BUFFER_POOLS > ODP_BUFFER_MAX_POOLS +#endif + +#define NULL_INDEX ((uint32_t)-1) + + +typedef union pool_entry_u { + struct pool_entry_s s; + + uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(struct pool_entry_s))]; + +} pool_entry_t; + + +typedef struct pool_table_t { + pool_entry_t pool[ODP_CONFIG_BUFFER_POOLS]; + +} pool_table_t; + + +/* The pool table */ +static pool_table_t *pool_tbl; + +/* Pool entry pointers (for inlining) */ +void *pool_entry_ptr[ODP_CONFIG_BUFFER_POOLS]; + + +int odp_buffer_pool_init_global(void) +{ + odp_buffer_pool_t i; + + pool_tbl = odp_shm_reserve("odp_buffer_pools", + sizeof(pool_table_t), + sizeof(pool_entry_t)); + + if (pool_tbl == NULL) + return -1; + + memset(pool_tbl, 0, sizeof(pool_table_t)); + + + for (i = 0; i < ODP_CONFIG_BUFFER_POOLS; i++) { + /* init locks */ + pool_entry_t *pool = &pool_tbl->pool[i]; + LOCK_INIT(&pool->s.lock); + pool->s.pool = i; + + pool_entry_ptr[i] = pool; + } + + ODP_DBG("\nBuffer pool init global\n"); + ODP_DBG(" pool_entry_s size %zu\n", sizeof(struct pool_entry_s)); + ODP_DBG(" pool_entry_t size %zu\n", sizeof(pool_entry_t)); + ODP_DBG(" odp_buffer_hdr_t size %zu\n", sizeof(odp_buffer_hdr_t)); + ODP_DBG("\n"); + + return 0; +} + + +odp_buffer_pool_t odp_buffer_pool_create(const char *name, + void *base_addr, uint64_t size, + size_t buf_size, size_t buf_align, + int buf_type) +{ + struct rte_mempool *pktmbuf_pool = NULL; + ODP_DBG("odp_buffer_pool_create: %s, %lx, %u, %u, %u, %d\n", name, + (uint64_t) base_addr, (unsigned) size, + (unsigned) buf_size, (unsigned) buf_align, + buf_type); + + pktmbuf_pool = + rte_mempool_create(name, NB_MBUF, + MBUF_SIZE, 32, + sizeof(struct rte_pktmbuf_pool_private), + rte_pktmbuf_pool_init, NULL, + rte_pktmbuf_init, NULL, + rte_socket_id(), 0); + if (pktmbuf_pool == NULL) { + ODP_ERR("Cannot init DPDK mbuf pool\n"); + return -1; + } + + return (odp_buffer_pool_t) pktmbuf_pool; +} + + +odp_buffer_pool_t odp_buffer_pool_lookup(const char *name) +{ + struct rte_mempool *mp = NULL; + + mp = rte_mempool_lookup(name); + if (mp == NULL) + return ODP_BUFFER_POOL_INVALID; + + return (odp_buffer_pool_t)mp; +} + + +odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id) +{ + return (odp_buffer_t)rte_pktmbuf_alloc((struct rte_mempool *)pool_id); +} + + +void odp_buffer_free(odp_buffer_t buf) +{ + rte_pktmbuf_free((struct rte_mbuf *)buf); +} + + +void odp_buffer_pool_print(odp_buffer_pool_t pool_id) +{ + rte_mempool_dump((const struct rte_mempool *)pool_id); +} diff --git a/platform/linux-dpdk/source/odp_init.c b/platform/linux-dpdk/source/odp_init.c new file mode 100644 index 0000000..ecc2066 --- /dev/null +++ b/platform/linux-dpdk/source/odp_init.c @@ -0,0 +1,113 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_init.h> +#include <odp_internal.h> +#include <odp_debug.h> +#include <odp_packet_dpdk.h> + +int odp_init_dpdk(void) +{ + int test_argc = 5; + char *test_argv[6]; + int core_count, i, num_cores = 0; + char core_mask[8]; + + core_count = odp_sys_core_count(); + for (i = 0; i < core_count; i++) + num_cores += (0x1 << i); + sprintf(core_mask, "%x", num_cores); + + test_argv[0] = malloc(sizeof("odp_dpdk")); + strcpy(test_argv[0], "odp_dpdk"); + test_argv[1] = malloc(sizeof("-c")); + strcpy(test_argv[1], "-c"); + test_argv[2] = malloc(sizeof(core_mask)); + strcpy(test_argv[2], core_mask); + test_argv[3] = malloc(sizeof("-n")); + strcpy(test_argv[3], "-n"); + test_argv[4] = malloc(sizeof("3")); + strcpy(test_argv[4], "3"); + + if (rte_eal_init(test_argc, (char **)test_argv) < 0) { + ODP_ERR("Cannot init the Intel DPDK EAL!"); + return -1; + } + + if (rte_pmd_init_all() < 0) { + ODP_ERR("Cannot init pmd\n"); + return -1; + } + + if (rte_eal_pci_probe() < 0) { + ODP_ERR("Cannot probe PCI\n"); + return -1; + } + + return 0; +} + +int odp_init_global(void) +{ + odp_thread_init_global(); + + odp_system_info_init(); + + if (odp_init_dpdk()) { + ODP_ERR("ODP dpdk init failed.\n"); + return -1; + } + + if (odp_shm_init_global()) { + ODP_ERR("ODP shm init failed.\n"); + return -1; + } + + if (odp_buffer_pool_init_global()) { + ODP_ERR("ODP buffer pool init failed.\n"); + return -1; + } + + if (odp_queue_init_global()) { + ODP_ERR("ODP queue init failed.\n"); + return -1; + } + + if (odp_schedule_init_global()) { + ODP_ERR("ODP schedule init failed.\n"); + return -1; + } + + if (odp_pktio_init_global()) { + ODP_ERR("ODP packet io init failed.\n"); + return -1; + } + + if (odp_timer_init_global()) { + ODP_ERR("ODP timer init failed.\n"); + return -1; + } + + return 0; +} + + +int odp_init_local(int thr_id) +{ + odp_thread_init_local(thr_id); + + if (odp_pktio_init_local()) { + ODP_ERR("ODP packet io local init failed.\n"); + return -1; + } + + if (odp_schedule_init_local()) { + ODP_ERR("ODP schedule local init failed.\n"); + return -1; + } + + return 0; +} diff --git a/platform/linux-dpdk/source/odp_packet.c b/platform/linux-dpdk/source/odp_packet.c new file mode 100644 index 0000000..c34e626 --- /dev/null +++ b/platform/linux-dpdk/source/odp_packet.c @@ -0,0 +1,374 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_packet.h> +#include <odp_packet_internal.h> +#include <odp_hints.h> +#include <odp_byteorder.h> + +#include <helper/odp_eth.h> +#include <helper/odp_ip.h> + +#include <string.h> +#include <stdio.h> + +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, odp_ipv4hdr_t *ipv4, + size_t *offset_out); +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, odp_ipv6hdr_t *ipv6, + size_t *offset_out); + +void odp_packet_init(odp_packet_t pkt) +{ + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr); + uint8_t *start; + size_t len; + + start = (uint8_t *)pkt_hdr + start_offset; + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; + memset(start, 0, len); + + pkt_hdr->l2_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; + pkt_hdr->l3_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; + pkt_hdr->l4_offset = (uint32_t) ODP_PACKET_OFFSET_INVALID; +} + +odp_packet_t odp_packet_from_buffer(odp_buffer_t buf) +{ + return (odp_packet_t)buf; +} + +odp_buffer_t odp_buffer_from_packet(odp_packet_t pkt) +{ + return (odp_buffer_t)pkt; +} + +void odp_packet_set_len(odp_packet_t pkt, size_t len) +{ + /* for rte_pktmbuf */ + odp_buffer_hdr_t *buf_hdr = odp_buf_to_hdr(odp_buffer_from_packet(pkt)); + buf_hdr->pkt.data_len = len; + + odp_packet_hdr(pkt)->frame_len = len; +} + +size_t odp_packet_get_len(odp_packet_t pkt) +{ + return odp_packet_hdr(pkt)->frame_len; +} + +uint8_t *odp_packet_buf_addr(odp_packet_t pkt) +{ + return odp_buffer_addr(odp_buffer_from_packet(pkt)); +} + +uint8_t *odp_packet_start(odp_packet_t pkt) +{ + return odp_packet_buf_addr(pkt) + odp_packet_hdr(pkt)->frame_offset; +} + + +uint8_t *odp_packet_l2(odp_packet_t pkt) +{ + const size_t offset = odp_packet_l2_offset(pkt); + + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) + return NULL; + + return odp_packet_buf_addr(pkt) + offset; +} + +size_t odp_packet_l2_offset(odp_packet_t pkt) +{ + return odp_packet_hdr(pkt)->l2_offset; +} + +void odp_packet_set_l2_offset(odp_packet_t pkt, size_t offset) +{ + odp_packet_hdr(pkt)->l2_offset = offset; +} + +uint8_t *odp_packet_l3(odp_packet_t pkt) +{ + const size_t offset = odp_packet_l3_offset(pkt); + + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) + return NULL; + + return odp_packet_buf_addr(pkt) + offset; +} + +size_t odp_packet_l3_offset(odp_packet_t pkt) +{ + return odp_packet_hdr(pkt)->l3_offset; +} + +void odp_packet_set_l3_offset(odp_packet_t pkt, size_t offset) +{ + odp_packet_hdr(pkt)->l3_offset = offset; +} + +uint8_t *odp_packet_l4(odp_packet_t pkt) +{ + const size_t offset = odp_packet_l4_offset(pkt); + + if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID)) + return NULL; + + return odp_packet_buf_addr(pkt) + offset; +} + +size_t odp_packet_l4_offset(odp_packet_t pkt) +{ + return odp_packet_hdr(pkt)->l4_offset; +} + +void odp_packet_set_l4_offset(odp_packet_t pkt, size_t offset) +{ + odp_packet_hdr(pkt)->l4_offset = offset; +} + +/** + * Simple packet parser: eth, VLAN, IP, TCP/UDP/ICMP + * + * Internal function: caller is resposible for passing only valid packet handles + * , lengths and offsets (usually done&called in packet input). + * + * @param pkt Packet handle + * @param len Packet length in bytes + * @param frame_offset Byte offset to L2 header + */ +void odp_packet_parse(odp_packet_t pkt, size_t len, size_t frame_offset) +{ + odp_packet_hdr_t *const pkt_hdr = odp_packet_hdr(pkt); + odp_ethhdr_t *eth; + odp_vlanhdr_t *vlan; + odp_ipv4hdr_t *ipv4; + odp_ipv6hdr_t *ipv6; + uint16_t ethtype; + size_t offset = 0; + uint8_t ip_proto = 0; + + pkt_hdr->input_flags.eth = 1; + pkt_hdr->frame_offset = frame_offset; + pkt_hdr->frame_len = len; + + if (odp_unlikely(len < ODP_ETH_LEN_MIN)) { + pkt_hdr->error_flags.frame_len = 1; + return; + } else if (len > ODP_ETH_LEN_MAX) { + pkt_hdr->input_flags.jumbo = 1; + } + + /* Assume valid L2 header, no CRC/FCS check in SW */ + pkt_hdr->input_flags.l2 = 1; + pkt_hdr->l2_offset = frame_offset; + + eth = (odp_ethhdr_t *)odp_packet_start(pkt); + ethtype = odp_be_to_cpu_16(eth->type); + vlan = (odp_vlanhdr_t *)ð->type; + + if (ethtype == ODP_ETHTYPE_VLAN_OUTER) { + pkt_hdr->input_flags.vlan_qinq = 1; + ethtype = odp_be_to_cpu_16(vlan->tpid); + offset += sizeof(odp_vlanhdr_t); + vlan = &vlan[1]; + } + + if (ethtype == ODP_ETHTYPE_VLAN) { + pkt_hdr->input_flags.vlan = 1; + ethtype = odp_be_to_cpu_16(vlan->tpid); + offset += sizeof(odp_vlanhdr_t); + } + + /* Set l3_offset+flag only for known ethtypes */ + switch (ethtype) { + case ODP_ETHTYPE_IPV4: + pkt_hdr->input_flags.ipv4 = 1; + pkt_hdr->input_flags.l3 = 1; + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + offset; + ipv4 = (odp_ipv4hdr_t *)odp_packet_l3(pkt); + ip_proto = parse_ipv4(pkt_hdr, ipv4, &offset); + break; + case ODP_ETHTYPE_IPV6: + pkt_hdr->input_flags.ipv6 = 1; + pkt_hdr->input_flags.l3 = 1; + pkt_hdr->l3_offset = frame_offset + ODP_ETHHDR_LEN + offset; + ipv6 = (odp_ipv6hdr_t *)odp_packet_l3(pkt); + ip_proto = parse_ipv6(pkt_hdr, ipv6, &offset); + break; + case ODP_ETHTYPE_ARP: + pkt_hdr->input_flags.arp = 1; + /* fall through */ + default: + ip_proto = 0; + break; + } + + switch (ip_proto) { + case ODP_IPPROTO_UDP: + pkt_hdr->input_flags.udp = 1; + pkt_hdr->input_flags.l4 = 1; + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; + break; + case ODP_IPPROTO_TCP: + pkt_hdr->input_flags.tcp = 1; + pkt_hdr->input_flags.l4 = 1; + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; + break; + case ODP_IPPROTO_SCTP: + pkt_hdr->input_flags.sctp = 1; + pkt_hdr->input_flags.l4 = 1; + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; + break; + case ODP_IPPROTO_ICMP: + pkt_hdr->input_flags.icmp = 1; + pkt_hdr->input_flags.l4 = 1; + pkt_hdr->l4_offset = pkt_hdr->l3_offset + offset; + break; + default: + /* 0 or unhandled IP protocols, don't set L4 flag+offset */ + if (pkt_hdr->input_flags.ipv6) { + /* IPv6 next_hdr is not L4, mark as IP-option instead */ + pkt_hdr->input_flags.ipopt = 1; + } + break; + } +} + +static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr, odp_ipv4hdr_t *ipv4, + size_t *offset_out) +{ + uint8_t ihl; + uint16_t frag_offset; + + ihl = ODP_IPV4HDR_IHL(ipv4->ver_ihl); + if (odp_unlikely(ihl < ODP_IPV4HDR_IHL_MIN)) { + pkt_hdr->error_flags.ip_err = 1; + return 0; + } + + if (odp_unlikely(ihl > ODP_IPV4HDR_IHL_MIN)) { + pkt_hdr->input_flags.ipopt = 1; + return 0; + } + + /* A packet is a fragment if: + * "more fragments" flag is set (all fragments except the last) + * OR + * "fragment offset" field is nonzero (all fragments except the first) + */ + frag_offset = odp_be_to_cpu_16(ipv4->frag_offset); + if (odp_unlikely(ODP_IPV4HDR_IS_FRAGMENT(frag_offset))) { + pkt_hdr->input_flags.ipfrag = 1; + return 0; + } + + if (ipv4->proto == ODP_IPPROTO_ESP || + ipv4->proto == ODP_IPPROTO_AH) { + pkt_hdr->input_flags.ipsec = 1; + return 0; + } + + /* Set pkt_hdr->input_flags.ipopt when checking L4 hdrs after return */ + + *offset_out = sizeof(uint32_t) * ihl; + return ipv4->proto; +} + +static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr, odp_ipv6hdr_t *ipv6, + size_t *offset_out) +{ + if (ipv6->next_hdr == ODP_IPPROTO_ESP || + ipv6->next_hdr == ODP_IPPROTO_AH) { + pkt_hdr->input_flags.ipopt = 1; + pkt_hdr->input_flags.ipsec = 1; + return 0; + } + + if (odp_unlikely(ipv6->next_hdr == ODP_IPPROTO_FRAG)) { + pkt_hdr->input_flags.ipopt = 1; + pkt_hdr->input_flags.ipfrag = 1; + return 0; + } + + /* Don't step through more extensions */ + *offset_out = ODP_IPV6HDR_LEN; + return ipv6->next_hdr; +} + +void odp_packet_print(odp_packet_t pkt) +{ + int max_len = 512; + char str[max_len]; + int len = 0; + int n = max_len-1; + odp_packet_hdr_t *hdr = odp_packet_hdr(pkt); + + len += snprintf(&str[len], n-len, "Packet "); + len += odp_buffer_snprint(&str[len], n-len, (odp_buffer_t) pkt); + len += snprintf(&str[len], n-len, + " input_flags 0x%x\n", hdr->input_flags.all); + len += snprintf(&str[len], n-len, + " error_flags 0x%x\n", hdr->error_flags.all); + len += snprintf(&str[len], n-len, + " output_flags 0x%x\n", hdr->output_flags.all); + len += snprintf(&str[len], n-len, + " frame_offset %u\n", hdr->frame_offset); + len += snprintf(&str[len], n-len, + " l2_offset %u\n", hdr->l2_offset); + len += snprintf(&str[len], n-len, + " l3_offset %u\n", hdr->l3_offset); + len += snprintf(&str[len], n-len, + " l4_offset %u\n", hdr->l4_offset); + len += snprintf(&str[len], n-len, + " frame_len %u\n", hdr->frame_len); + len += snprintf(&str[len], n-len, + " input %u\n", hdr->input); + str[len] = '\0'; + + printf("\n%s\n", str); +} + +int odp_packet_copy(odp_packet_t pkt_dst, odp_packet_t pkt_src) +{ + odp_packet_hdr_t *const pkt_hdr_dst = odp_packet_hdr(pkt_dst); + odp_packet_hdr_t *const pkt_hdr_src = odp_packet_hdr(pkt_src); + const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr); + uint8_t *start_src; + uint8_t *start_dst; + size_t len; + + if (pkt_dst == ODP_PACKET_INVALID || pkt_src == ODP_PACKET_INVALID) + return -1; + + /* if (pkt_hdr_dst->buf_hdr.size < */ + /* pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) */ + if (pkt_hdr_dst->buf_hdr.buf_len < + pkt_hdr_src->frame_len + pkt_hdr_src->frame_offset) + return -1; + + /* Copy packet header */ + start_dst = (uint8_t *)pkt_hdr_dst + start_offset; + start_src = (uint8_t *)pkt_hdr_src + start_offset; + len = ODP_OFFSETOF(odp_packet_hdr_t, payload) - start_offset; + memcpy(start_dst, start_src, len); + + /* Copy frame payload */ + start_dst = (uint8_t *)odp_packet_start(pkt_dst); + start_src = (uint8_t *)odp_packet_start(pkt_src); + len = pkt_hdr_src->frame_len; + memcpy(start_dst, start_src, len); + + /* Copy useful things from the buffer header */ + /* pkt_hdr_dst->buf_hdr.cur_offset = pkt_hdr_src->buf_hdr.cur_offset; */ + + /* Create a copy of the scatter list */ + /* odp_buffer_copy_scatter(odp_buffer_from_packet(pkt_dst), */ + /* odp_buffer_from_packet(pkt_src)); */ + + return 0; +} diff --git a/platform/linux-dpdk/source/odp_packet_dpdk.c b/platform/linux-dpdk/source/odp_packet_dpdk.c new file mode 100644 index 0000000..6d16bbe --- /dev/null +++ b/platform/linux-dpdk/source/odp_packet_dpdk.c @@ -0,0 +1,177 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <poll.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +#include <linux/ethtool.h> +#include <linux/sockios.h> + +#include <odp_hints.h> +#include <odp_thread.h> + +#include <odp_packet_dpdk.h> +#include <net/if.h> + +/* + * RX and TX Prefetch, Host, and Write-back threshold values should be + * carefully set for optimal performance. Consult the network + * controller's datasheet and supporting DPDK documentation for guidance + * on how these parameters should be set. + */ +#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ +#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ +#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */ + +/* + * These default values are optimized for use with the Intel(R) 82599 10 GbE + * Controller and the DPDK ixgbe PMD. Consider using other values for other + * network controllers and/or network drivers. + */ +#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */ +#define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ +#define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ + +#define MAX_PKT_BURST 32 +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ +#define RTE_TEST_RX_DESC_DEFAULT 128 +#define RTE_TEST_TX_DESC_DEFAULT 512 +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; + +static const struct rte_eth_conf port_conf = { + .rxmode = { + .split_hdr_size = 0, + .header_split = 0, /**< Header Split disabled */ + .hw_ip_checksum = 0, /**< IP checksum offload disabled */ + .hw_vlan_filter = 0, /**< VLAN filtering disabled */ + .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ + .hw_strip_crc = 0, /**< CRC stripped by hardware */ + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, +}; + +static const struct rte_eth_rxconf rx_conf = { + .rx_thresh = { + .pthresh = RX_PTHRESH, + .hthresh = RX_HTHRESH, + .wthresh = RX_WTHRESH, + }, +}; + +static const struct rte_eth_txconf tx_conf = { + .tx_thresh = { + .pthresh = TX_PTHRESH, + .hthresh = TX_HTHRESH, + .wthresh = TX_WTHRESH, + }, + .tx_free_thresh = 0, /* Use PMD default values */ + .tx_rs_thresh = 0, /* Use PMD default values */ + /* + * As the example won't handle mult-segments and offload cases, + * set the flag by default. + */ + .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, +}; + +int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev, + odp_buffer_pool_t pool) +{ + ODP_DBG("setup_pkt_dpdk\n"); + + static struct ether_addr eth_addr[RTE_MAX_ETHPORTS]; + uint8_t portid = 0; + uint16_t queueid = 0; + int ret; + printf("vincent netdev: %s\n", netdev); + printf("vincent pool: %lx\n", pool); + + portid = atoi(netdev); + pkt_dpdk->portid = portid; + pkt_dpdk->queueid = queueid; + pkt_dpdk->pool = pool; + printf("vincent portid: %u\n", portid); + + fflush(stdout); + ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); + if (ret < 0) + ODP_ERR("Cannot configure device: err=%d, port=%u\n", + ret, (unsigned) portid); + + rte_eth_macaddr_get(portid, ð_addr[portid]); + ODP_DBG("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", + (unsigned) portid, + eth_addr[portid].addr_bytes[0], + eth_addr[portid].addr_bytes[1], + eth_addr[portid].addr_bytes[2], + eth_addr[portid].addr_bytes[3], + eth_addr[portid].addr_bytes[4], + eth_addr[portid].addr_bytes[5]); + + /* init one RX queue on each port */ + fflush(stdout); + ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, + rte_eth_dev_socket_id(portid), &rx_conf, + (struct rte_mempool *)pool); + if (ret < 0) + ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n", + ret, (unsigned) portid); + ODP_DBG("dpdk rx queue setup done\n"); + + /* init one TX queue on each port */ + fflush(stdout); + ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, + rte_eth_dev_socket_id(portid), &tx_conf); + if (ret < 0) + ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n", + ret, (unsigned) portid); + ODP_DBG("dpdk tx queue setup done\n"); + + /* Start device */ + ret = rte_eth_dev_start(portid); + if (ret < 0) + ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n", + ret, (unsigned) portid); + ODP_DBG("dpdk setup done\n\n"); + + + return 0; +} + +int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk) +{ + ODP_DBG("close pkt_dpdk, %u\n", pkt_dpdk->portid); + + return 0; +} + +int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], + unsigned len) +{ + return rte_eth_rx_burst((uint8_t)pkt_dpdk->portid, + (uint16_t)pkt_dpdk->queueid, + (struct rte_mbuf **)pkt_table, (uint16_t)len); +} + +int send_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[], + unsigned len) +{ + return rte_eth_tx_burst((uint8_t)pkt_dpdk->portid, + (uint16_t)pkt_dpdk->queueid, + (struct rte_mbuf **)pkt_table, (uint16_t)len); +} diff --git a/platform/linux-dpdk/source/odp_packet_io.c b/platform/linux-dpdk/source/odp_packet_io.c new file mode 100644 index 0000000..abea0ec --- /dev/null +++ b/platform/linux-dpdk/source/odp_packet_io.c @@ -0,0 +1,561 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_packet_io.h> +#include <odp_packet_io_internal.h> +#include <odp_packet_io_queue.h> +#include <odp_packet.h> +#include <odp_packet_internal.h> +#include <odp_internal.h> +#include <odp_spinlock.h> +#include <odp_shared_memory.h> +#include <odp_packet_socket.h> +#ifdef ODP_HAVE_NETMAP +#include <odp_packet_netmap.h> +#endif +#include <odp_hints.h> +#include <odp_config.h> +#include <odp_queue_internal.h> +#include <odp_schedule_internal.h> +#include <odp_debug.h> + +#include <odp_pktio_socket.h> +#ifdef ODP_HAVE_NETMAP +#include <odp_pktio_netmap.h> +#endif + +#include <string.h> + +typedef struct { + pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES]; +} pktio_table_t; + +static pktio_table_t *pktio_tbl; + + +static pktio_entry_t *get_entry(odp_pktio_t id) +{ + if (odp_unlikely(id == ODP_PKTIO_INVALID || + id > ODP_CONFIG_PKTIO_ENTRIES)) + return NULL; + + return &pktio_tbl->entries[id - 1]; +} + +int odp_pktio_init_global(void) +{ + char name[ODP_QUEUE_NAME_LEN]; + pktio_entry_t *pktio_entry; + queue_entry_t *queue_entry; + odp_queue_t qid; + int id; + + pktio_tbl = odp_shm_reserve("odp_pktio_entries", + sizeof(pktio_table_t), + sizeof(pktio_entry_t)); + if (pktio_tbl == NULL) + return -1; + + memset(pktio_tbl, 0, sizeof(pktio_table_t)); + + for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) { + pktio_entry = get_entry(id); + + odp_spinlock_init(&pktio_entry->s.lock); + + /* Create a default output queue for each pktio resource */ + snprintf(name, sizeof(name), "%i-pktio_outq_default", (int)id); + name[ODP_QUEUE_NAME_LEN-1] = '\0'; + + qid = odp_queue_create(name, ODP_QUEUE_TYPE_PKTOUT, NULL); + if (qid == ODP_QUEUE_INVALID) + return -1; + pktio_entry->s.outq_default = qid; + + queue_entry = queue_to_qentry(qid); + queue_entry->s.pktout = id; + } + + return 0; +} + +int odp_pktio_init_local(void) +{ + return 0; +} + +static int is_free(pktio_entry_t *entry) +{ + return (entry->s.taken == 0); +} + +static void set_free(pktio_entry_t *entry) +{ + entry->s.taken = 0; +} + +static void set_taken(pktio_entry_t *entry) +{ + entry->s.taken = 1; +} + +static void lock_entry(pktio_entry_t *entry) +{ + odp_spinlock_lock(&entry->s.lock); +} + +static void unlock_entry(pktio_entry_t *entry) +{ + odp_spinlock_unlock(&entry->s.lock); +} + +static void init_pktio_entry(pktio_entry_t *entry, odp_pktio_params_t *params) +{ + set_taken(entry); + entry->s.inq_default = ODP_QUEUE_INVALID; + switch (params->type) { + case ODP_PKTIO_TYPE_SOCKET_BASIC: + case ODP_PKTIO_TYPE_SOCKET_MMSG: + case ODP_PKTIO_TYPE_SOCKET_MMAP: + memset(&entry->s.pkt_sock, 0, sizeof(entry->s.pkt_sock)); + memset(&entry->s.pkt_sock_mmap, 0, + sizeof(entry->s.pkt_sock_mmap)); + break; +#ifdef ODP_HAVE_NETMAP + case ODP_PKTIO_TYPE_NETMAP: + memset(&entry->s.pkt_nm, 0, sizeof(entry->s.pkt_nm)); + break; +#endif + case ODP_PKTIO_TYPE_DPDK: + memset(&entry->s.pkt_dpdk, 0, sizeof(entry->s.pkt_dpdk)); + break; + default: + ODP_ERR("Packet I/O type not supported. Please recompile\n"); + break; + } + /* Save pktio parameters, type is the most useful */ + memcpy(&entry->s.params, params, sizeof(*params)); +} + +static odp_pktio_t alloc_lock_pktio_entry(odp_pktio_params_t *params) +{ + odp_pktio_t id; + pktio_entry_t *entry; + int i; + + for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) { + entry = &pktio_tbl->entries[i]; + if (is_free(entry)) { + lock_entry(entry); + if (is_free(entry)) { + init_pktio_entry(entry, params); + id = i + 1; + return id; /* return with entry locked! */ + } + unlock_entry(entry); + } + } + + return ODP_PKTIO_INVALID; +} + +static int free_pktio_entry(odp_pktio_t id) +{ + pktio_entry_t *entry = get_entry(id); + + if (entry == NULL) + return -1; + + set_free(entry); + + return 0; +} + +odp_pktio_t odp_pktio_open(const char *dev, odp_buffer_pool_t pool, + odp_pktio_params_t *params) +{ + odp_pktio_t id; + pktio_entry_t *pktio_entry; + int res; + + if (params == NULL) { + ODP_ERR("Invalid pktio params\n"); + return ODP_PKTIO_INVALID; + } + + switch (params->type) { + case ODP_PKTIO_TYPE_SOCKET_BASIC: + case ODP_PKTIO_TYPE_SOCKET_MMSG: + case ODP_PKTIO_TYPE_SOCKET_MMAP: + ODP_DBG("Allocating socket pktio\n"); + break; +#ifdef ODP_HAVE_NETMAP + case ODP_PKTIO_TYPE_NETMAP: + ODP_DBG("Allocating netmap pktio\n"); + break; +#endif + case ODP_PKTIO_TYPE_DPDK: + ODP_DBG("Allocating dpdk pktio\n"); + break; + default: + ODP_ERR("Invalid pktio type: %02x\n", params->type); + return ODP_PKTIO_INVALID; + } + + id = alloc_lock_pktio_entry(params); + if (id == ODP_PKTIO_INVALID) { + ODP_ERR("No resources available.\n"); + return ODP_PKTIO_INVALID; + } + /* if successful, alloc_pktio_entry() returns with the entry locked */ + + pktio_entry = get_entry(id); + + switch (params->type) { + case ODP_PKTIO_TYPE_SOCKET_BASIC: + case ODP_PKTIO_TYPE_SOCKET_MMSG: + res = setup_pkt_sock(&pktio_entry->s.pkt_sock, dev, pool); + if (res == -1) { + close_pkt_sock(&pktio_entry->s.pkt_sock); + free_pktio_entry(id); + id = ODP_PKTIO_INVALID; + } + break; + case ODP_PKTIO_TYPE_SOCKET_MMAP: + res = setup_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, dev, + pool, params->sock_params.fanout); + if (res == -1) { + close_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap); + free_pktio_entry(id); + id = ODP_PKTIO_INVALID; + } + break; +#ifdef ODP_HAVE_NETMAP + case ODP_PKTIO_TYPE_NETMAP: + + res = setup_pkt_netmap(&pktio_entry->s.pkt_nm, dev, + pool, ¶ms->nm_params); + if (res == -1) { + close_pkt_netmap(&pktio_entry->s.pkt_nm); + free_pktio_entry(id); + id = ODP_PKTIO_INVALID; + } + break; +#endif + case ODP_PKTIO_TYPE_DPDK: + res = setup_pkt_dpdk(&pktio_entry->s.pkt_dpdk, dev, pool); + if (res == -1) { + close_pkt_dpdk(&pktio_entry->s.pkt_dpdk); + free_pktio_entry(id); + id = ODP_PKTIO_INVALID; + } + break; + default: + free_pktio_entry(id); + id = ODP_PKTIO_INVALID; + ODP_ERR("Invalid pktio type. Please recompile.\n"); + break; + } + + unlock_entry(pktio_entry); + return id; +} + +int odp_pktio_close(odp_pktio_t id) +{ + pktio_entry_t *entry; + int res = -1; + + entry = get_entry(id); + if (entry == NULL) + return -1; + + lock_entry(entry); + if (!is_free(entry)) { + switch (entry->s.params.type) { + case ODP_PKTIO_TYPE_SOCKET_BASIC: + case ODP_PKTIO_TYPE_SOCKET_MMSG: + res = close_pkt_sock(&entry->s.pkt_sock); + break; + case ODP_PKTIO_TYPE_SOCKET_MMAP: + res = close_pkt_sock_mmap(&entry->s.pkt_sock_mmap); + break; +#ifdef ODP_HAVE_NETMAP + case ODP_PKTIO_TYPE_NETMAP: + res = close_pkt_netmap(&entry->s.pkt_nm); + break; +#endif + case ODP_PKTIO_TYPE_DPDK: + res = close_pkt_dpdk(&entry->s.pkt_dpdk); + break; + default: + break; + res |= free_pktio_entry(id); + } + } + unlock_entry(entry); + + if (res != 0) + return -1; + + return 0; +} + +void odp_pktio_set_input(odp_packet_t pkt, odp_pktio_t pktio) +{ + odp_packet_hdr(pkt)->input = pktio; +} + +odp_pktio_t odp_pktio_get_input(odp_packet_t pkt) +{ + return odp_packet_hdr(pkt)->input; +} + +int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len) +{ + pktio_entry_t *pktio_entry = get_entry(id); + int pkts; + int i; + + if (pktio_entry == NULL) + return -1; + + lock_entry(pktio_entry); + switch (pktio_entry->s.params.type) { + case ODP_PKTIO_TYPE_SOCKET_BASIC: + pkts = recv_pkt_sock_basic(&pktio_entry->s.pkt_sock, + pkt_table, len); + break; + case ODP_PKTIO_TYPE_SOCKET_MMSG: + pkts = recv_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, + pkt_table, len); + break; + case ODP_PKTIO_TYPE_SOCKET_MMAP: + pkts = recv_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, + pkt_table, len); + break; +#ifdef ODP_HAVE_NETMAP + case ODP_PKTIO_TYPE_NETMAP: + pkts = recv_pkt_netmap(&pktio_entry->s.pkt_nm, pkt_table, len); + break; +#endif + case ODP_PKTIO_TYPE_DPDK: + pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, len); + break; + default: + pkts = -1; + break; + } + + unlock_entry(pktio_entry); + if (pkts < 0) + return pkts; + + for (i = 0; i < pkts; ++i) + odp_pktio_set_input(pkt_table[i], id); + + return pkts; +} + +int odp_pktio_send(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len) +{ + pktio_entry_t *pktio_entry = get_entry(id); + int pkts; + + if (pktio_entry == NULL) + return -1; + + lock_entry(pktio_entry); + switch (pktio_entry->s.params.type) { + case ODP_PKTIO_TYPE_SOCKET_BASIC: + pkts = send_pkt_sock_basic(&pktio_entry->s.pkt_sock, + pkt_table, len); + break; + case ODP_PKTIO_TYPE_SOCKET_MMSG: + pkts = send_pkt_sock_mmsg(&pktio_entry->s.pkt_sock, + pkt_table, len); + break; + case ODP_PKTIO_TYPE_SOCKET_MMAP: + pkts = send_pkt_sock_mmap(&pktio_entry->s.pkt_sock_mmap, + pkt_table, len); + break; +#ifdef ODP_HAVE_NETMAP + case ODP_PKTIO_TYPE_NETMAP: + pkts = send_pkt_netmap(&pktio_entry->s.pkt_nm, + pkt_table, len); + break; +#endif + case ODP_PKTIO_TYPE_DPDK: + pkts = send_pkt_dpdk(&pktio_entry->s.pkt_dpdk, + pkt_table, len); + break; + default: + pkts = -1; + } + unlock_entry(pktio_entry); + + return pkts; +} + +int odp_pktio_inq_setdef(odp_pktio_t id, odp_queue_t queue) +{ + pktio_entry_t *pktio_entry = get_entry(id); + queue_entry_t *qentry = queue_to_qentry(queue); + + if (pktio_entry == NULL || qentry == NULL) + return -1; + + if (qentry->s.type != ODP_QUEUE_TYPE_PKTIN) + return -1; + + lock_entry(pktio_entry); + pktio_entry->s.inq_default = queue; + unlock_entry(pktio_entry); + + queue_lock(qentry); + qentry->s.pktin = id; + qentry->s.status = QUEUE_STATUS_SCHED; + queue_unlock(qentry); + + odp_schedule_queue(queue, qentry->s.param.sched.prio); + + return 0; +} + +int odp_pktio_inq_remdef(odp_pktio_t id) +{ + return odp_pktio_inq_setdef(id, ODP_QUEUE_INVALID); +} + +odp_queue_t odp_pktio_inq_getdef(odp_pktio_t id) +{ + pktio_entry_t *pktio_entry = get_entry(id); + + if (pktio_entry == NULL) + return ODP_QUEUE_INVALID; + + return pktio_entry->s.inq_default; +} + +odp_queue_t odp_pktio_outq_getdef(odp_pktio_t id) +{ + pktio_entry_t *pktio_entry = get_entry(id); + + if (pktio_entry == NULL) + return ODP_QUEUE_INVALID; + + return pktio_entry->s.outq_default; +} + +int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) +{ + odp_packet_t pkt = odp_packet_from_buffer((odp_buffer_t) buf_hdr); + int len = 1; + int nbr; + + nbr = odp_pktio_send(qentry->s.pktout, &pkt, len); + return (nbr == len ? 0 : -1); +} + +odp_buffer_hdr_t *pktout_dequeue(queue_entry_t *qentry) +{ + (void)qentry; + return NULL; +} + +int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], + int num) +{ + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; + int nbr; + int i; + + for (i = 0; i < num; ++i) + pkt_tbl[i] = odp_packet_from_buffer((odp_buffer_t) buf_hdr[i]); + + nbr = odp_pktio_send(qentry->s.pktout, pkt_tbl, num); + return (nbr == num ? 0 : -1); +} + +int pktout_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], + int num) +{ + (void)qentry; + (void)buf_hdr; + (void)num; + + return 0; +} + +int pktin_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) +{ + /* Use default action */ + return queue_enq(qentry, buf_hdr); +} + +odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry) +{ + odp_buffer_hdr_t *buf_hdr; + + buf_hdr = queue_deq(qentry); + + if (buf_hdr == NULL) { + odp_packet_t pkt; + odp_buffer_t buf; + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; + int pkts, i, j; + + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, + QUEUE_MULTI_MAX); + + if (pkts > 0) { + pkt = pkt_tbl[0]; + buf = odp_buffer_from_packet(pkt); + buf_hdr = odp_buf_to_hdr(buf); + + for (i = 1, j = 0; i < pkts; ++i) { + buf = odp_buffer_from_packet(pkt_tbl[i]); + tmp_hdr_tbl[j++] = odp_buf_to_hdr(buf); + } + queue_enq_multi(qentry, tmp_hdr_tbl, j); + } + } + + return buf_hdr; +} + +int pktin_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num) +{ + /* Use default action */ + return queue_enq_multi(qentry, buf_hdr, num); +} + +int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num) +{ + int nbr; + + nbr = queue_deq_multi(qentry, buf_hdr, num); + + if (nbr < num) { + odp_packet_t pkt_tbl[QUEUE_MULTI_MAX]; + odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX]; + odp_buffer_t buf; + int pkts, i; + + pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, + QUEUE_MULTI_MAX); + if (pkts > 0) { + for (i = 0; i < pkts; ++i) { + buf = odp_buffer_from_packet(pkt_tbl[i]); + tmp_hdr_tbl[i] = odp_buf_to_hdr(buf); + } + queue_enq_multi(qentry, tmp_hdr_tbl, pkts); + } + } + + return nbr; +} diff --git a/platform/linux-dpdk/source/odp_queue.c b/platform/linux-dpdk/source/odp_queue.c new file mode 100644 index 0000000..554b8ea --- /dev/null +++ b/platform/linux-dpdk/source/odp_queue.c @@ -0,0 +1,435 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_queue.h> +#include <odp_queue_internal.h> +#include <odp_std_types.h> +#include <odp_align.h> +#include <odp_buffer.h> +#include <odp_buffer_internal.h> +#include <odp_buffer_pool_internal.h> +#include <odp_internal.h> +#include <odp_shared_memory.h> +#include <odp_schedule_internal.h> +#include <odp_config.h> +#include <odp_packet_io_internal.h> +#include <odp_packet_io_queue.h> +#include <odp_debug.h> +#include <odp_hints.h> + +#ifdef USE_TICKETLOCK +#include <odp_ticketlock.h> +#define LOCK(a) odp_ticketlock_lock(a) +#define UNLOCK(a) odp_ticketlock_unlock(a) +#define LOCK_INIT(a) odp_ticketlock_init(a) +#else +#include <odp_spinlock.h> +#define LOCK(a) odp_spinlock_lock(a) +#define UNLOCK(a) odp_spinlock_unlock(a) +#define LOCK_INIT(a) odp_spinlock_init(a) +#endif + +#include <string.h> + + +typedef struct queue_table_t { + queue_entry_t queue[ODP_CONFIG_QUEUES]; +} queue_table_t; + +static queue_table_t *queue_tbl; + + +queue_entry_t *get_qentry(uint32_t queue_id) +{ + return &queue_tbl->queue[queue_id]; +} + +static void queue_init(queue_entry_t *queue, const char *name, + odp_queue_type_t type, odp_queue_param_t *param) +{ + strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1); + queue->s.type = type; + + if (param) { + memcpy(&queue->s.param, param, sizeof(odp_queue_param_t)); + } else { + /* Defaults */ + memset(&queue->s.param, 0, sizeof(odp_queue_param_t)); + queue->s.param.sched.prio = ODP_SCHED_PRIO_DEFAULT; + queue->s.param.sched.sync = ODP_SCHED_SYNC_DEFAULT; + queue->s.param.sched.group = ODP_SCHED_GROUP_DEFAULT; + } + + switch (type) { + case ODP_QUEUE_TYPE_PKTIN: + queue->s.enqueue = pktin_enqueue; + queue->s.dequeue = pktin_dequeue; + queue->s.enqueue_multi = pktin_enq_multi; + queue->s.dequeue_multi = pktin_deq_multi; + break; + case ODP_QUEUE_TYPE_PKTOUT: + queue->s.enqueue = pktout_enqueue; + queue->s.dequeue = pktout_dequeue; + queue->s.enqueue_multi = pktout_enq_multi; + queue->s.dequeue_multi = pktout_deq_multi; + break; + default: + queue->s.enqueue = queue_enq; + queue->s.dequeue = queue_deq; + queue->s.enqueue_multi = queue_enq_multi; + queue->s.dequeue_multi = queue_deq_multi; + break; + } + + queue->s.head = NULL; + queue->s.tail = NULL; + queue->s.sched_buf = ODP_BUFFER_INVALID; +} + + +int odp_queue_init_global(void) +{ + uint32_t i; + + ODP_DBG("Queue init ... "); + + queue_tbl = odp_shm_reserve("odp_queues", + sizeof(queue_table_t), + sizeof(queue_entry_t)); + + if (queue_tbl == NULL) + return -1; + + memset(queue_tbl, 0, sizeof(queue_table_t)); + + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { + /* init locks */ + queue_entry_t *queue = get_qentry(i); + LOCK_INIT(&queue->s.lock); + queue->s.handle = queue_from_id(i); + } + + ODP_DBG("done\n"); + ODP_DBG("Queue init global\n"); + ODP_DBG(" struct queue_entry_s size %zu\n", + sizeof(struct queue_entry_s)); + ODP_DBG(" queue_entry_t size %zu\n", + sizeof(queue_entry_t)); + ODP_DBG("\n"); + + return 0; +} + +odp_queue_type_t odp_queue_type(odp_queue_t handle) +{ + queue_entry_t *queue; + + queue = queue_to_qentry(handle); + + return queue->s.type; +} + +odp_schedule_sync_t odp_queue_sched_type(odp_queue_t handle) +{ + queue_entry_t *queue; + + queue = queue_to_qentry(handle); + + return queue->s.param.sched.sync; +} + +odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type, + odp_queue_param_t *param) +{ + uint32_t i; + queue_entry_t *queue; + odp_queue_t handle = ODP_QUEUE_INVALID; + + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { + queue = &queue_tbl->queue[i]; + + if (queue->s.status != QUEUE_STATUS_FREE) + continue; + + LOCK(&queue->s.lock); + if (queue->s.status == QUEUE_STATUS_FREE) { + queue_init(queue, name, type, param); + + if (type == ODP_QUEUE_TYPE_SCHED || + type == ODP_QUEUE_TYPE_PKTIN) + queue->s.status = QUEUE_STATUS_NOTSCHED; + else + queue->s.status = QUEUE_STATUS_READY; + + handle = queue->s.handle; + UNLOCK(&queue->s.lock); + break; + } + UNLOCK(&queue->s.lock); + } + + if (handle != ODP_QUEUE_INVALID && + (type == ODP_QUEUE_TYPE_SCHED || type == ODP_QUEUE_TYPE_PKTIN)) { + odp_buffer_t buf; + + buf = odp_schedule_buffer_alloc(handle); + if (buf == ODP_BUFFER_INVALID) { + ODP_ERR("queue_init: sched buf alloc failed\n"); + return ODP_QUEUE_INVALID; + } + + queue->s.sched_buf = buf; + odp_schedule_mask_set(handle, queue->s.param.sched.prio); + } + + return handle; +} + + +odp_buffer_t queue_sched_buf(odp_queue_t handle) +{ + queue_entry_t *queue; + queue = queue_to_qentry(handle); + + return queue->s.sched_buf; +} + + +int queue_sched_atomic(odp_queue_t handle) +{ + queue_entry_t *queue; + queue = queue_to_qentry(handle); + + return queue->s.param.sched.sync == ODP_SCHED_SYNC_ATOMIC; +} + + +odp_queue_t odp_queue_lookup(const char *name) +{ + uint32_t i; + + for (i = 0; i < ODP_CONFIG_QUEUES; i++) { + queue_entry_t *queue = &queue_tbl->queue[i]; + + if (queue->s.status == QUEUE_STATUS_FREE) + continue; + + LOCK(&queue->s.lock); + if (strcmp(name, queue->s.name) == 0) { + /* found it */ + UNLOCK(&queue->s.lock); + return queue->s.handle; + } + UNLOCK(&queue->s.lock); + } + + return ODP_QUEUE_INVALID; +} + + +int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr) +{ + int sched = 0; + + LOCK(&queue->s.lock); + if (queue->s.head == NULL) { + /* Empty queue */ + queue->s.head = buf_hdr; + queue->s.tail = buf_hdr; + buf_hdr->pkt.next = NULL; + } else { + queue->s.tail->pkt.next = buf_hdr; + queue->s.tail = buf_hdr; + buf_hdr->pkt.next = NULL; + } + + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { + queue->s.status = QUEUE_STATUS_SCHED; + sched = 1; /* retval: schedule queue */ + } + UNLOCK(&queue->s.lock); + + /* Add queue to scheduling */ + if (sched == 1) + odp_schedule_queue(queue->s.handle, queue->s.param.sched.prio); + + return 0; +} + + +int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], int num) +{ + int sched = 0; + int i; + odp_buffer_hdr_t *tail; + + for (i = 0; i < num - 1; i++) + buf_hdr[i]->pkt.next = buf_hdr[i+1]; + + tail = buf_hdr[num-1]; + buf_hdr[num-1]->pkt.next = NULL; + + LOCK(&queue->s.lock); + /* Empty queue */ + if (queue->s.head == NULL) + queue->s.head = buf_hdr[0]; + else + queue->s.tail->pkt.next = buf_hdr[0]; + + queue->s.tail = tail; + + if (queue->s.status == QUEUE_STATUS_NOTSCHED) { + queue->s.status = QUEUE_STATUS_SCHED; + sched = 1; /* retval: schedule queue */ + } + UNLOCK(&queue->s.lock); + + /* Add queue to scheduling */ + if (sched == 1) + odp_schedule_queue(queue->s.handle, queue->s.param.sched.prio); + + return 0; +} + + +int odp_queue_enq_multi(odp_queue_t handle, odp_buffer_t buf[], int num) +{ + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; + queue_entry_t *queue; + int i; + + if (num > QUEUE_MULTI_MAX) + num = QUEUE_MULTI_MAX; + + queue = queue_to_qentry(handle); + + for (i = 0; i < num; i++) + buf_hdr[i] = odp_buf_to_hdr(buf[i]); + + return queue->s.enqueue_multi(queue, buf_hdr, num); +} + + +int odp_queue_enq(odp_queue_t handle, odp_buffer_t buf) +{ + odp_buffer_hdr_t *buf_hdr; + queue_entry_t *queue; + + queue = queue_to_qentry(handle); + buf_hdr = odp_buf_to_hdr(buf); + + return queue->s.enqueue(queue, buf_hdr); +} + + +odp_buffer_hdr_t *queue_deq(queue_entry_t *queue) +{ + odp_buffer_hdr_t *buf_hdr = NULL; + + LOCK(&queue->s.lock); + + if (queue->s.head == NULL) { + /* Already empty queue */ + if (queue->s.status == QUEUE_STATUS_SCHED && + queue->s.type != ODP_QUEUE_TYPE_PKTIN) + queue->s.status = QUEUE_STATUS_NOTSCHED; + } else { + buf_hdr = queue->s.head; + queue->s.head = buf_hdr->pkt.next; + buf_hdr->pkt.next = NULL; + + if (queue->s.head == NULL) { + /* Queue is now empty */ + queue->s.tail = NULL; + } + } + + UNLOCK(&queue->s.lock); + + return buf_hdr; +} + + +int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], int num) +{ + int i = 0; + + LOCK(&queue->s.lock); + + if (queue->s.head == NULL) { + /* Already empty queue */ + if (queue->s.status == QUEUE_STATUS_SCHED && + queue->s.type != ODP_QUEUE_TYPE_PKTIN) + queue->s.status = QUEUE_STATUS_NOTSCHED; + } else { + odp_buffer_hdr_t *hdr = queue->s.head; + + for (; i < num && hdr; i++) { + buf_hdr[i] = hdr; + /* odp_prefetch(hdr->addr); */ + hdr = hdr->pkt.next; + buf_hdr[i]->pkt.next = NULL; + } + + queue->s.head = hdr; + + if (hdr == NULL) { + /* Queue is now empty */ + queue->s.tail = NULL; + } + } + + UNLOCK(&queue->s.lock); + + return i; +} + + +int odp_queue_deq_multi(odp_queue_t handle, odp_buffer_t buf[], int num) +{ + queue_entry_t *queue; + odp_buffer_hdr_t *buf_hdr[QUEUE_MULTI_MAX]; + int i, ret; + + if (num > QUEUE_MULTI_MAX) + num = QUEUE_MULTI_MAX; + + queue = queue_to_qentry(handle); + + ret = queue->s.dequeue_multi(queue, buf_hdr, num); + + for (i = 0; i < ret; i++) + buf[i] = (odp_buffer_t) buf_hdr[i]; + + return ret; +} + + +odp_buffer_t odp_queue_deq(odp_queue_t handle) +{ + queue_entry_t *queue; + odp_buffer_hdr_t *buf_hdr; + + queue = queue_to_qentry(handle); + buf_hdr = queue->s.dequeue(queue); + + if (buf_hdr) + return (odp_buffer_t) buf_hdr; + + return ODP_BUFFER_INVALID; +} + + +void queue_lock(queue_entry_t *queue) +{ + LOCK(&queue->s.lock); +} + + +void queue_unlock(queue_entry_t *queue) +{ + UNLOCK(&queue->s.lock); +}