aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-generic
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linux-generic')
-rw-r--r--platform/linux-generic/Makefile.am5
-rw-r--r--platform/linux-generic/arch/aarch64/cpu_flags.c19
-rw-r--r--platform/linux-generic/arch/aarch64/odp_crypto_armv8.c38
-rw-r--r--platform/linux-generic/include/odp/api/plat/packet_inline_types.h7
-rw-r--r--platform/linux-generic/include/odp_align_internal.h67
-rw-r--r--platform/linux-generic/include/odp_buffer_internal.h1
-rw-r--r--platform/linux-generic/include/odp_classification_datamodel.h9
-rw-r--r--platform/linux-generic/include/odp_macros_internal.h63
-rw-r--r--platform/linux-generic/include/odp_packet_dpdk.h10
-rw-r--r--platform/linux-generic/include/odp_packet_internal.h39
-rw-r--r--platform/linux-generic/include/odp_packet_io_internal.h7
-rw-r--r--platform/linux-generic/include/odp_parse_internal.h4
-rw-r--r--platform/linux-generic/include/odp_pool_internal.h33
-rw-r--r--platform/linux-generic/include/odp_queue_basic_internal.h4
-rw-r--r--platform/linux-generic/include/odp_queue_scalable_internal.h6
-rw-r--r--platform/linux-generic/include/odp_ring_internal.h4
-rw-r--r--platform/linux-generic/include/odp_ring_mpmc_internal.h3
-rw-r--r--platform/linux-generic/include/odp_ring_st_internal.h2
-rw-r--r--platform/linux-generic/include/odp_schedule_if.h1
-rw-r--r--platform/linux-generic/include/odp_schedule_scalable_ordered.h5
-rw-r--r--platform/linux-generic/libodp-linux.pc.in2
-rw-r--r--platform/linux-generic/m4/configure.m43
-rw-r--r--platform/linux-generic/m4/odp_xdp.m415
-rw-r--r--platform/linux-generic/odp_classification.c116
-rw-r--r--platform/linux-generic/odp_crypto_null.c5
-rw-r--r--platform/linux-generic/odp_crypto_openssl.c8
-rw-r--r--platform/linux-generic/odp_ipsec.c7
-rw-r--r--platform/linux-generic/odp_ipsec_sad.c9
-rw-r--r--platform/linux-generic/odp_ishm.c1
-rw-r--r--platform/linux-generic/odp_ishmphy.c1
-rw-r--r--platform/linux-generic/odp_ishmpool.c13
-rw-r--r--platform/linux-generic/odp_name_table.c12
-rw-r--r--platform/linux-generic/odp_packet.c4
-rw-r--r--platform/linux-generic/odp_pcapng.c19
-rw-r--r--platform/linux-generic/odp_pkt_queue.c6
-rw-r--r--platform/linux-generic/odp_pool.c108
-rw-r--r--platform/linux-generic/odp_pool_mem_src_ops.c22
-rw-r--r--platform/linux-generic/odp_queue_basic.c7
-rw-r--r--platform/linux-generic/odp_queue_scalable.c10
-rw-r--r--platform/linux-generic/odp_schedule_basic.c12
-rw-r--r--platform/linux-generic/odp_schedule_if.c5
-rw-r--r--platform/linux-generic/odp_schedule_scalable.c6
-rw-r--r--platform/linux-generic/odp_schedule_sp.c9
-rw-r--r--platform/linux-generic/odp_stash.c11
-rw-r--r--platform/linux-generic/odp_timer.c8
-rw-r--r--platform/linux-generic/odp_timer_wheel.c2
-rw-r--r--platform/linux-generic/odp_traffic_mngr.c47
-rw-r--r--platform/linux-generic/pktio/dpdk.c116
-rw-r--r--platform/linux-generic/pktio/io_ops.c3
-rw-r--r--platform/linux-generic/pktio/ipc.c12
-rw-r--r--platform/linux-generic/pktio/loop.c15
-rw-r--r--platform/linux-generic/pktio/netmap.c12
-rw-r--r--platform/linux-generic/pktio/socket.c2
-rw-r--r--platform/linux-generic/pktio/socket_mmap.c4
-rw-r--r--platform/linux-generic/pktio/socket_xdp.c688
55 files changed, 1247 insertions, 400 deletions
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index d4e94f677..6e64df740 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -17,6 +17,7 @@ AM_CPPFLAGS += $(NETMAP_CPPFLAGS)
AM_CFLAGS += $(AARCH64CRYPTO_CFLAGS)
AM_CFLAGS += $(DPDK_CFLAGS)
AM_CFLAGS += $(LIBCONFIG_CFLAGS)
+AM_CFLAGS += $(LIBXDP_CFLAGS)
DISTCLEANFILES = include/odp_libconfig_config.h
include/odp_libconfig_config.h: $(top_builddir)/$(rel_default_config_path) $(top_builddir)/config.status
@@ -105,7 +106,6 @@ odpapiabiarchinclude_HEADERS += \
endif
noinst_HEADERS = \
- include/odp_align_internal.h \
include/odp_atomic_internal.h \
include/odp_bitset.h \
include/odp_buffer_internal.h \
@@ -210,6 +210,7 @@ __LIB__libodp_linux_la_SOURCES = \
odp_parse.c \
odp_pkt_queue.c \
odp_pool.c \
+ odp_pool_mem_src_ops.c \
odp_queue_basic.c \
odp_queue_if.c \
odp_queue_lf.c \
@@ -256,6 +257,7 @@ __LIB__libodp_linux_la_SOURCES = \
pktio/pktio_common.c \
pktio/socket.c \
pktio/socket_mmap.c \
+ pktio/socket_xdp.c \
pktio/tap.c
if WITH_OPENSSL_CRYPTO
@@ -418,6 +420,7 @@ __LIB__libodp_linux_la_LIBADD += $(LIBCONFIG_LIBS)
__LIB__libodp_linux_la_LIBADD += $(DPDK_LIBS_LIBODP)
__LIB__libodp_linux_la_LIBADD += $(PTHREAD_LIBS)
__LIB__libodp_linux_la_LIBADD += $(TIMER_LIBS)
+__LIB__libodp_linux_la_LIBADD += $(LIBXDP_LIBS)
if ODP_PKTIO_PCAP
__LIB__libodp_linux_la_LIBADD += $(PCAP_LIBS)
diff --git a/platform/linux-generic/arch/aarch64/cpu_flags.c b/platform/linux-generic/arch/aarch64/cpu_flags.c
index d70e26271..e013f749f 100644
--- a/platform/linux-generic/arch/aarch64/cpu_flags.c
+++ b/platform/linux-generic/arch/aarch64/cpu_flags.c
@@ -1,19 +1,22 @@
/* Copyright (c) 2018, Linaro Limited
- * Copyright (c) 2020-2021, Nokia
+ * Copyright (c) 2020-2022, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <string.h>
-#include <stdlib.h>
-#include <sys/auxv.h>
-#include <asm/hwcap.h>
-
#include <odp/api/hints.h>
+
#include <odp_debug_internal.h>
+#include <odp_macros_internal.h>
+
#include "cpu_flags.h"
+#include <asm/hwcap.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/auxv.h>
+
typedef struct {
const char *feat_flag;
const unsigned int hwcap_field;
@@ -895,7 +898,7 @@ static void _odp_sys_info_print_hwcap_flags(void)
/* Print supported hardware flags via AT_HWCAP entry of the hwcaps
* auxiliary vector. */
hwcaps = getauxval(AT_HWCAP);
- size = sizeof(hwcap_flags) / sizeof(hwcap_feat_flag_t);
+ size = _ODP_ARRAY_SIZE(hwcap_flags);
for (unsigned int i = 0; i < size; i++) {
if (hwcap_flags[i].valid) {
if (check_hwcap_duplicates(hwcap_flags[i].hwcap_field)) {
@@ -912,7 +915,7 @@ static void _odp_sys_info_print_hwcap_flags(void)
/* Print supported hardware flags via AT_HWCAP2 entry of the hwcaps
* auxiliary vector. */
hwcaps2 = getauxval(AT_HWCAP2);
- size2 = sizeof(hwcap2_flags) / sizeof(hwcap_feat_flag_t);
+ size2 = _ODP_ARRAY_SIZE(hwcap2_flags);
for (unsigned long i = 0; i < size2; i++) {
if (hwcap2_flags[i].valid) {
if (hwcaps2 & 0x01)
diff --git a/platform/linux-generic/arch/aarch64/odp_crypto_armv8.c b/platform/linux-generic/arch/aarch64/odp_crypto_armv8.c
index 4d46846ce..4531ebc28 100644
--- a/platform/linux-generic/arch/aarch64/odp_crypto_armv8.c
+++ b/platform/linux-generic/arch/aarch64/odp_crypto_armv8.c
@@ -95,9 +95,9 @@ typedef struct odp_crypto_generic_session_t odp_crypto_generic_session_t;
* Algorithm handler function prototype
*/
typedef
-odp_bool_t (*crypto_func_t)(odp_packet_t pkt,
- const odp_crypto_packet_op_param_t *param,
- odp_crypto_generic_session_t *session);
+void (*crypto_func_t)(odp_packet_t pkt,
+ const odp_crypto_packet_op_param_t *param,
+ odp_crypto_generic_session_t *session);
/**
* Per crypto session data structure
@@ -204,13 +204,12 @@ static inline void set_crypto_op_result_ok(odp_packet_t pkt)
ODP_CRYPTO_ALG_ERR_NONE);
}
-static odp_bool_t
+static void
null_crypto_routine(odp_packet_t pkt ODP_UNUSED,
const odp_crypto_packet_op_param_t *param ODP_UNUSED,
odp_crypto_generic_session_t *session ODP_UNUSED)
{
set_crypto_op_result_ok(pkt);
- return true;
}
static inline void copy_aad(uint8_t *dst, uint8_t *src, uint32_t len)
@@ -225,9 +224,9 @@ static inline void copy_aad(uint8_t *dst, uint8_t *src, uint32_t len)
}
static
-odp_bool_t aes_gcm_encrypt(odp_packet_t pkt,
- const odp_crypto_packet_op_param_t *param,
- odp_crypto_generic_session_t *session)
+void aes_gcm_encrypt(odp_packet_t pkt,
+ const odp_crypto_packet_op_param_t *param,
+ odp_crypto_generic_session_t *session)
{
armv8_cipher_state_t cs = {
.counter = {
@@ -257,7 +256,7 @@ odp_bool_t aes_gcm_encrypt(odp_packet_t pkt,
else if (session->p.cipher_iv.data)
iv_ptr = session->cipher.iv_data;
else
- return ODP_CRYPTO_ALG_ERR_IV_INVALID;
+ goto err;
#else
iv_ptr = param->cipher_iv_ptr;
ODP_ASSERT(session->p.cipher_iv_len == 0 || iv_ptr != NULL);
@@ -316,19 +315,18 @@ odp_bool_t aes_gcm_encrypt(odp_packet_t pkt,
}
set_crypto_op_result_ok(pkt);
- return true;
+ return;
err:
set_crypto_op_result(pkt,
ODP_CRYPTO_ALG_ERR_DATA_SIZE,
ODP_CRYPTO_ALG_ERR_NONE);
- return false;
}
static
-odp_bool_t aes_gcm_decrypt(odp_packet_t pkt,
- const odp_crypto_packet_op_param_t *param,
- odp_crypto_generic_session_t *session)
+void aes_gcm_decrypt(odp_packet_t pkt,
+ const odp_crypto_packet_op_param_t *param,
+ odp_crypto_generic_session_t *session)
{
armv8_cipher_state_t cs = {
.counter = {
@@ -358,7 +356,7 @@ odp_bool_t aes_gcm_decrypt(odp_packet_t pkt,
else if (session->p.cipher_iv.data)
iv_ptr = session->cipher.iv_data;
else
- return ODP_CRYPTO_ALG_ERR_IV_INVALID;
+ goto err;
#else
iv_ptr = param->cipher_iv_ptr;
ODP_ASSERT(session->p.cipher_iv_len == 0 || iv_ptr != NULL);
@@ -416,13 +414,12 @@ odp_bool_t aes_gcm_decrypt(odp_packet_t pkt,
odp_packet_copy_from_mem(pkt, in_pos, in_len, data);
set_crypto_op_result_ok(pkt);
- return true;
+ return;
err:
set_crypto_op_result(pkt,
ODP_CRYPTO_ALG_ERR_NONE,
ODP_CRYPTO_ALG_ERR_ICV_CHECK);
- return false;
}
static int process_aes_gcm_param(odp_crypto_generic_session_t *session)
@@ -724,7 +721,6 @@ odp_crypto_operation(odp_crypto_op_param_t *param,
* We cannot fail since odp_crypto_op() has already processed
* the packet. Let's indicate error in the result instead.
*/
- packet_hdr(out_pkt)->p.flags.crypto_err = 1;
packet_result.ok = false;
}
@@ -916,8 +912,6 @@ int crypto_int(odp_packet_t pkt_in,
odp_crypto_generic_session_t *session;
odp_bool_t allocated = false;
odp_packet_t out_pkt = *pkt_out;
- odp_packet_hdr_t *pkt_hdr;
- odp_bool_t ok;
session = (odp_crypto_generic_session_t *)(intptr_t)param->session;
@@ -959,11 +953,9 @@ int crypto_int(odp_packet_t pkt_in,
}
/* Invoke the crypto function */
- ok = session->func(out_pkt, param, session);
+ session->func(out_pkt, param, session);
packet_subtype_set(out_pkt, ODP_EVENT_PACKET_CRYPTO);
- pkt_hdr = packet_hdr(out_pkt);
- pkt_hdr->p.flags.crypto_err = !ok;
/* Synchronous, simply return results */
*pkt_out = out_pkt;
diff --git a/platform/linux-generic/include/odp/api/plat/packet_inline_types.h b/platform/linux-generic/include/odp/api/plat/packet_inline_types.h
index 126404f2d..c5293fc86 100644
--- a/platform/linux-generic/include/odp/api/plat/packet_inline_types.h
+++ b/platform/linux-generic/include/odp/api/plat/packet_inline_types.h
@@ -115,7 +115,7 @@ typedef union {
uint32_t all_flags;
struct {
- uint32_t reserved1: 6;
+ uint32_t reserved1: 7;
/*
* Init flags
@@ -146,14 +146,13 @@ typedef union {
uint32_t udp_err: 1; /* UDP error */
uint32_t sctp_err: 1; /* SCTP error */
uint32_t l4_chksum_err: 1; /* L4 checksum error */
- uint32_t crypto_err: 1; /* Crypto packet operation error */
};
/* Flag groups */
struct {
- uint32_t reserved2: 6;
+ uint32_t reserved2: 7;
uint32_t other: 18; /* All other flags */
- uint32_t error: 8; /* All error flags */
+ uint32_t error: 7; /* All error flags */
} all;
} _odp_packet_flags_t;
diff --git a/platform/linux-generic/include/odp_align_internal.h b/platform/linux-generic/include/odp_align_internal.h
deleted file mode 100644
index df2182df2..000000000
--- a/platform/linux-generic/include/odp_align_internal.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (c) 2014-2018, Linaro Limited
- * All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/**
- * @file
- *
- * ODP internal alignments
- */
-
-#ifndef ODP_ALIGN_INTERNAL_H_
-#define ODP_ALIGN_INTERNAL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <odp/api/align.h>
-#include <stdint.h>
-
-/* Macros to calculate ODP_ROUNDUP_POWER2_U32() in five rounds of shift
- * and OR operations. */
-#define _RSHIFT_U32(x, y) (((uint32_t)(x)) >> (y))
-#define _POW2_U32_R1(x) (((uint32_t)(x)) | _RSHIFT_U32(x, 1))
-#define _POW2_U32_R2(x) (_POW2_U32_R1(x) | _RSHIFT_U32(_POW2_U32_R1(x), 2))
-#define _POW2_U32_R3(x) (_POW2_U32_R2(x) | _RSHIFT_U32(_POW2_U32_R2(x), 4))
-#define _POW2_U32_R4(x) (_POW2_U32_R3(x) | _RSHIFT_U32(_POW2_U32_R3(x), 8))
-#define _POW2_U32_R5(x) (_POW2_U32_R4(x) | _RSHIFT_U32(_POW2_U32_R4(x), 16))
-
-/* Round up a uint32_t value 'x' to the next power of two.
- *
- * The value is not round up, if it's already a power of two (including 1).
- * The value must be larger than 0 and not exceed 0x80000000.
- */
-#define ROUNDUP_POWER2_U32(x) \
- ((((uint32_t)(x)) > 0x80000000) ? 0 : (_POW2_U32_R5(x - 1) + 1))
-
-/*
- * Round up 'x' to alignment 'align'
- */
-#define ROUNDUP_ALIGN(x, align)\
- ((align) * (((x) + (align) - 1) / (align)))
-
-/*
- * Round up 'x' to cache line size alignment
- */
-#define ROUNDUP_CACHE_LINE(x)\
- ROUNDUP_ALIGN(x, ODP_CACHE_LINE_SIZE)
-
-/*
- * Round down 'x' to 'align' alignment, which is a power of two
- */
-#define ROUNDDOWN_POWER2(x, align)\
- ((x) & (~((align) - 1)))
-
-/*
- * Check if value is a power of two
- */
-#define CHECK_IS_POWER2(x) ((((x) - 1) & (x)) == 0)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/platform/linux-generic/include/odp_buffer_internal.h b/platform/linux-generic/include/odp_buffer_internal.h
index e0be593d0..5841720ef 100644
--- a/platform/linux-generic/include/odp_buffer_internal.h
+++ b/platform/linux-generic/include/odp_buffer_internal.h
@@ -24,7 +24,6 @@ extern "C" {
#include <odp/api/buffer.h>
#include <odp/api/debug.h>
#include <odp/api/align.h>
-#include <odp_align_internal.h>
#include <odp_config_internal.h>
#include <odp/api/byteorder.h>
#include <odp/api/thread.h>
diff --git a/platform/linux-generic/include/odp_classification_datamodel.h b/platform/linux-generic/include/odp_classification_datamodel.h
index 6b50fef68..6e89a9947 100644
--- a/platform/linux-generic/include/odp_classification_datamodel.h
+++ b/platform/linux-generic/include/odp_classification_datamodel.h
@@ -21,10 +21,13 @@ extern "C" {
#include <odp/api/spinlock.h>
#include <odp/api/classification.h>
#include <odp/api/debug.h>
+
+#include <odp_macros_internal.h>
#include <odp_pool_internal.h>
#include <odp_packet_internal.h>
#include <odp_packet_io_internal.h>
#include <odp_queue_if.h>
+
#include <protocols/ip.h>
/* Maximum Class Of Service Entry */
@@ -155,7 +158,7 @@ struct cos_s {
typedef union cos_u {
struct cos_s s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct cos_s))];
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(struct cos_s))];
} cos_t;
/* Pattern Matching Rule */
@@ -172,7 +175,7 @@ struct pmr_s {
typedef union pmr_u {
struct pmr_s s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct pmr_s))];
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(struct pmr_s))];
} pmr_t;
typedef struct _cls_queue_grp_tbl_s {
@@ -181,7 +184,7 @@ typedef struct _cls_queue_grp_tbl_s {
typedef union _cls_queue_grp_tbl_t {
_cls_queue_grp_tbl_s s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(_cls_queue_grp_tbl_s))];
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(_cls_queue_grp_tbl_s))];
} _cls_queue_grp_tbl_t;
/**
diff --git a/platform/linux-generic/include/odp_macros_internal.h b/platform/linux-generic/include/odp_macros_internal.h
index b8be7f938..abf017aec 100644
--- a/platform/linux-generic/include/odp_macros_internal.h
+++ b/platform/linux-generic/include/odp_macros_internal.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2018-2018, Linaro Limited
+/* Copyright (c) 2014-2018, Linaro Limited
+ * Copyright (c) 2022, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -17,37 +18,67 @@
extern "C" {
#endif
-#include <odp/api/debug.h>
+#include <odp/api/align.h>
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#include <stdint.h>
-#define MIN(a, b) \
+#define _ODP_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define _ODP_MIN(a, b) \
__extension__ ({ \
__typeof__(a) tmp_a = (a); \
__typeof__(b) tmp_b = (b); \
tmp_a < tmp_b ? tmp_a : tmp_b; \
})
-#define MAX(a, b) \
+#define _ODP_MAX(a, b) \
__extension__ ({ \
__typeof__(a) tmp_a = (a); \
__typeof__(b) tmp_b = (b); \
tmp_a > tmp_b ? tmp_a : tmp_b; \
})
-#define MAX3(a, b, c) (MAX(MAX((a), (b)), (c)))
+#define _ODP_MAX3(a, b, c) (_ODP_MAX(_ODP_MAX((a), (b)), (c)))
-#define odp_container_of(pointer, type, member) \
- ((type *)(void *)(((char *)pointer) - offsetof(type, member)))
+/* Macros to calculate ODP_ROUNDUP_POWER2_U32() in five rounds of shift
+ * and OR operations. */
+#define __ODP_RSHIFT_U32(x, y) (((uint32_t)(x)) >> (y))
+#define __ODP_POW2_U32_R1(x) (((uint32_t)(x)) | __ODP_RSHIFT_U32(x, 1))
+#define __ODP_POW2_U32_R2(x) (__ODP_POW2_U32_R1(x) | __ODP_RSHIFT_U32(__ODP_POW2_U32_R1(x), 2))
+#define __ODP_POW2_U32_R3(x) (__ODP_POW2_U32_R2(x) | __ODP_RSHIFT_U32(__ODP_POW2_U32_R2(x), 4))
+#define __ODP_POW2_U32_R4(x) (__ODP_POW2_U32_R3(x) | __ODP_RSHIFT_U32(__ODP_POW2_U32_R3(x), 8))
+#define __ODP_POW2_U32_R5(x) (__ODP_POW2_U32_R4(x) | __ODP_RSHIFT_U32(__ODP_POW2_U32_R4(x), 16))
-#define DIV_ROUND_UP(a, b) \
- __extension__ ({ \
- __typeof__(a) tmp_a = (a); \
- __typeof__(b) tmp_b = (b); \
- ODP_STATIC_ASSERT(__builtin_constant_p(b), ""); \
- ODP_STATIC_ASSERT((((b) - 1) & (b)) == 0, ""); \
- (tmp_a + tmp_b - 1) >> __builtin_ctz(tmp_b); \
- })
+/* Round up a uint32_t value 'x' to the next power of two.
+ *
+ * The value is not round up, if it's already a power of two (including 1).
+ * The value must be larger than 0 and not exceed 0x80000000.
+ */
+#define _ODP_ROUNDUP_POWER2_U32(x) \
+ ((((uint32_t)(x)) > 0x80000000) ? 0 : (__ODP_POW2_U32_R5(x - 1) + 1))
+
+/*
+ * Round up 'x' to alignment 'align'
+ */
+#define _ODP_ROUNDUP_ALIGN(x, align)\
+ ((align) * (((x) + (align) - 1) / (align)))
+
+/*
+ * Round up 'x' to cache line size alignment
+ */
+#define _ODP_ROUNDUP_CACHE_LINE(x)\
+ _ODP_ROUNDUP_ALIGN(x, ODP_CACHE_LINE_SIZE)
+
+/*
+ * Round down 'x' to 'align' alignment, which is a power of two
+ */
+#define _ODP_ROUNDDOWN_POWER2(x, align)\
+ ((x) & (~((align) - 1)))
+
+/*
+ * Check if value is a power of two
+ */
+#define _ODP_CHECK_IS_POWER2(x) ((((x) - 1) & (x)) == 0)
#ifdef __cplusplus
}
diff --git a/platform/linux-generic/include/odp_packet_dpdk.h b/platform/linux-generic/include/odp_packet_dpdk.h
index b326000e6..7d42971be 100644
--- a/platform/linux-generic/include/odp_packet_dpdk.h
+++ b/platform/linux-generic/include/odp_packet_dpdk.h
@@ -26,16 +26,6 @@ struct rte_mbuf;
#define PTYPE_UDP 0x20
#define PTYPE_TCP 0x40
-/**
- * Calculate size of zero-copy DPDK packet pool object
- */
-uint32_t _odp_dpdk_pool_obj_size(pool_t *pool, uint32_t block_size);
-
-/**
- * Create zero-copy DPDK packet pool
- */
-int _odp_dpdk_pool_create(pool_t *pool);
-
/** Packet parser using DPDK interface */
int _odp_dpdk_packet_parse_common(packet_parser_t *pkt_hdr,
const uint8_t *ptr,
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
index a8f58146a..e54d88f6a 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -21,19 +21,21 @@ extern "C" {
#include <odp/api/align.h>
#include <odp/api/atomic.h>
#include <odp/api/debug.h>
+#include <odp/api/hints.h>
#include <odp/api/packet.h>
-#include <odp/api/plat/packet_inline_types.h>
#include <odp/api/packet_io.h>
#include <odp/api/crypto.h>
#include <odp/api/comp.h>
#include <odp/api/std.h>
-#include <odp/api/abi/packet.h>
+
+#include <odp/api/plat/packet_inline_types.h>
#include <odp_debug_internal.h>
#include <odp_event_internal.h>
#include <odp_ipsec_internal.h>
#include <odp_pool_internal.h>
#include <odp_queue_if.h>
+#include <odp_config_internal.h>
#include <stdint.h>
#include <string.h>
@@ -44,12 +46,6 @@ ODP_STATIC_ASSERT(sizeof(_odp_packet_input_flags_t) == sizeof(uint64_t),
ODP_STATIC_ASSERT(sizeof(_odp_packet_flags_t) == sizeof(uint32_t),
"PACKET_FLAGS_SIZE_ERROR");
-/* Packet extra data length */
-#define PKT_EXTRA_LEN 128
-
-/* Packet extra data types */
-#define PKT_EXTRA_TYPE_DPDK 1
-
/* Maximum number of segments per packet */
#define PKT_MAX_SEGS 255
@@ -150,14 +146,15 @@ typedef struct ODP_ALIGNED_CACHE odp_packet_hdr_t {
/* LSO profile index */
uint8_t lso_profile_idx;
+ /* Pktio where packet is used as a memory source */
+ uint8_t ms_pktio_idx;
+
union {
- struct {
- /* Result for crypto packet op */
- odp_crypto_packet_result_t crypto_op_result;
+ /* Result for crypto packet op */
+ odp_crypto_packet_result_t crypto_op_result;
- /* Context for IPsec */
- odp_ipsec_packet_result_t ipsec_ctx;
- };
+ /* Context for IPsec */
+ odp_ipsec_packet_result_t ipsec_ctx;
/* Result for comp packet op */
odp_comp_packet_result_t comp_op_result;
@@ -172,6 +169,8 @@ typedef struct ODP_ALIGNED_CACHE odp_packet_hdr_t {
* grow over 256 bytes. */
ODP_STATIC_ASSERT(sizeof(odp_packet_hdr_t) <= 256, "PACKET_HDR_SIZE_ERROR");
+ODP_STATIC_ASSERT(ODP_CONFIG_PKTIO_ENTRIES < UINT8_MAX, "MS_PKTIO_IDX_SIZE_ERROR");
+
/**
* Return the packet header
*/
@@ -298,6 +297,8 @@ static inline void _odp_packet_copy_md(odp_packet_hdr_t *dst_hdr,
odp_packet_hdr_t *src_hdr,
odp_bool_t uarea_copy)
{
+ int8_t subtype = src_hdr->subtype;
+
/* Lengths and segmentation data are not copied:
* .frame_len
* .headroom
@@ -308,6 +309,7 @@ static inline void _odp_packet_copy_md(odp_packet_hdr_t *dst_hdr,
* .seg_count
*/
dst_hdr->input = src_hdr->input;
+ dst_hdr->subtype = subtype;
dst_hdr->dst_queue = src_hdr->dst_queue;
dst_hdr->cos = src_hdr->cos;
dst_hdr->cls_mark = src_hdr->cls_mark;
@@ -351,6 +353,15 @@ static inline void _odp_packet_copy_md(odp_packet_hdr_t *dst_hdr,
dst_hdr->uarea_addr = src_uarea;
}
}
+
+ if (odp_unlikely(subtype != ODP_EVENT_PACKET_BASIC)) {
+ if (subtype == ODP_EVENT_PACKET_IPSEC)
+ dst_hdr->ipsec_ctx = src_hdr->ipsec_ctx;
+ else if (subtype == ODP_EVENT_PACKET_CRYPTO)
+ dst_hdr->crypto_op_result = src_hdr->crypto_op_result;
+ else if (subtype == ODP_EVENT_PACKET_COMP)
+ dst_hdr->comp_op_result = src_hdr->comp_op_result;
+ }
}
static inline void _odp_packet_copy_cls_md(odp_packet_hdr_t *dst_hdr,
diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h
index aed6de412..ca9f083da 100644
--- a/platform/linux-generic/include/odp_packet_io_internal.h
+++ b/platform/linux-generic/include/odp_packet_io_internal.h
@@ -26,10 +26,10 @@ extern "C" {
#include <odp/api/plat/packet_io_inlines.h>
#include <odp/autoheader_internal.h>
-#include <odp_align_internal.h>
#include <odp_classification_datamodel.h>
#include <odp_config_internal.h>
#include <odp_debug_internal.h>
+#include <odp_macros_internal.h>
#include <odp_packet_io_stats_common.h>
#include <odp_queue_if.h>
@@ -70,7 +70,7 @@ struct pktio_if_ops;
#elif defined(_ODP_PKTIO_DPDK)
#define PKTIO_PRIVATE_SIZE 5632
#else
-#define PKTIO_PRIVATE_SIZE 384
+#define PKTIO_PRIVATE_SIZE 512
#endif
struct pktio_entry {
@@ -173,7 +173,7 @@ struct pktio_entry {
typedef union {
struct pktio_entry s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct pktio_entry))];
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(struct pktio_entry))];
} pktio_entry_t;
typedef struct {
@@ -308,6 +308,7 @@ static inline void _odp_pktio_tx_ts_set(pktio_entry_t *entry)
extern const pktio_if_ops_t _odp_netmap_pktio_ops;
extern const pktio_if_ops_t _odp_dpdk_pktio_ops;
+extern const pktio_if_ops_t _odp_sock_xdp_pktio_ops;
extern const pktio_if_ops_t _odp_sock_mmsg_pktio_ops;
extern const pktio_if_ops_t _odp_sock_mmap_pktio_ops;
extern const pktio_if_ops_t _odp_loopback_pktio_ops;
diff --git a/platform/linux-generic/include/odp_parse_internal.h b/platform/linux-generic/include/odp_parse_internal.h
index 8aa5e118b..22d8c2cf6 100644
--- a/platform/linux-generic/include/odp_parse_internal.h
+++ b/platform/linux-generic/include/odp_parse_internal.h
@@ -45,8 +45,8 @@ extern "C" {
#define PARSE_SCTP_BYTES (sizeof(_odp_sctphdr_t))
/* _odp_packet_parse_common_l3_l4() requires up to this many bytes. */
-#define PARSE_L3_L4_BYTES (MAX(PARSE_IPV4_BYTES, PARSE_IPV6_BYTES) + \
- MAX3(PARSE_TCP_BYTES, PARSE_UDP_BYTES, PARSE_SCTP_BYTES))
+#define PARSE_L3_L4_BYTES (_ODP_MAX(PARSE_IPV4_BYTES, PARSE_IPV6_BYTES) + \
+ _ODP_MAX3(PARSE_TCP_BYTES, PARSE_UDP_BYTES, PARSE_SCTP_BYTES))
/* _odp_packet_parse_common() requires up to this many bytes. */
#define PARSE_BYTES (PARSE_ETH_BYTES + PARSE_L3_L4_BYTES)
diff --git a/platform/linux-generic/include/odp_pool_internal.h b/platform/linux-generic/include/odp_pool_internal.h
index 4c9f9a9ce..824aa9292 100644
--- a/platform/linux-generic/include/odp_pool_internal.h
+++ b/platform/linux-generic/include/odp_pool_internal.h
@@ -28,6 +28,8 @@ extern "C" {
#include <odp_ring_ptr_internal.h>
#include <odp/api/plat/strong_types.h>
+#define _ODP_POOL_MEM_SRC_DATA_SIZE 128
+
typedef struct ODP_ALIGNED_CACHE pool_cache_t {
/* Number of buffers in cache */
uint32_t cache_num;
@@ -52,8 +54,7 @@ typedef struct ODP_ALIGNED_CACHE {
} pool_ring_t;
#pragma GCC diagnostic pop
-/* Callback function for pool destroy */
-typedef void (*pool_destroy_cb_fn)(void *pool);
+struct _odp_pool_mem_src_ops_t;
typedef struct pool_t {
odp_ticketlock_t lock ODP_ALIGNED_CACHE;
@@ -91,14 +92,11 @@ typedef struct pool_t {
uint8_t *uarea_base_addr;
odp_pool_type_t type_2;
odp_pool_ext_param_t ext_param;
-
- /* Used by DPDK zero-copy pktio */
- uint32_t dpdk_elt_size;
uint32_t skipped_blocks;
- uint8_t pool_in_use;
uint8_t mem_from_huge_pages;
- pool_destroy_cb_fn ext_destroy;
- void *ext_desc;
+ const struct _odp_pool_mem_src_ops_t *mem_src_ops;
+ /* Private area for memory source operations */
+ uint8_t mem_src_data[_ODP_POOL_MEM_SRC_DATA_SIZE] ODP_ALIGNED_CACHE;
struct ODP_ALIGNED_CACHE {
odp_atomic_u64_t alloc_ops;
@@ -130,6 +128,25 @@ typedef struct pool_global_t {
} pool_global_t;
+/* Operations for when ODP packet pool is used as a memory source for e.g. zero-copy packet IO
+ * purposes */
+typedef struct _odp_pool_mem_src_ops_t {
+ /* Name of the ops provider */
+ const char *name;
+ /* Signal if ops provider is an active user for the pool as a memory source */
+ odp_bool_t (*is_active)(void);
+ /* Force disable for the ops provider (for now, if one active memory source user is found,
+ * others are disabled) */
+ void (*force_disable)(void);
+ /* Adjust pool block sizes as required by memory consumer */
+ void (*adjust_size)(uint8_t *data, uint32_t *block_size, uint32_t *block_offset,
+ uint32_t *flags);
+ /* Bind the pool as a memory source */
+ int (*bind)(uint8_t *data, pool_t *pool);
+ /* Unbind the pool as a memory source */
+ void (*unbind)(uint8_t *data);
+} _odp_pool_mem_src_ops_t;
+
extern pool_global_t *_odp_pool_glb;
static inline pool_t *pool_entry(uint32_t pool_idx)
diff --git a/platform/linux-generic/include/odp_queue_basic_internal.h b/platform/linux-generic/include/odp_queue_basic_internal.h
index d8a3226cb..9babb62e9 100644
--- a/platform/linux-generic/include/odp_queue_basic_internal.h
+++ b/platform/linux-generic/include/odp_queue_basic_internal.h
@@ -17,12 +17,12 @@ extern "C" {
#include <odp_forward_typedefs_internal.h>
#include <odp_queue_if.h>
#include <odp_buffer_internal.h>
-#include <odp_align_internal.h>
#include <odp/api/packet_io.h>
#include <odp/api/align.h>
#include <odp/api/hints.h>
#include <odp/api/ticketlock.h>
#include <odp_config_internal.h>
+#include <odp_macros_internal.h>
#include <odp_ring_mpmc_internal.h>
#include <odp_ring_st_internal.h>
#include <odp_ring_spsc_internal.h>
@@ -69,7 +69,7 @@ struct queue_entry_s {
union queue_entry_u {
struct queue_entry_s s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct queue_entry_s))];
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(struct queue_entry_s))];
};
typedef struct queue_global_t {
diff --git a/platform/linux-generic/include/odp_queue_scalable_internal.h b/platform/linux-generic/include/odp_queue_scalable_internal.h
index 6f9b85c85..3c74d1699 100644
--- a/platform/linux-generic/include/odp_queue_scalable_internal.h
+++ b/platform/linux-generic/include/odp_queue_scalable_internal.h
@@ -18,12 +18,12 @@ extern "C" {
#include <odp_forward_typedefs_internal.h>
#include <odp_queue_if.h>
#include <odp_event_internal.h>
-#include <odp_align_internal.h>
#include <odp/api/packet_io.h>
#include <odp/api/align.h>
#include <odp/api/hints.h>
#include <odp/api/ticketlock.h>
#include <odp_config_internal.h>
+#include <odp_macros_internal.h>
#include <odp_schedule_scalable.h>
#include <odp_schedule_scalable_ordered.h>
@@ -55,7 +55,7 @@ struct queue_entry_s {
union queue_entry_u {
struct queue_entry_s s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct queue_entry_s))];
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(struct queue_entry_s))];
};
int _odp_queue_deq(sched_elem_t *q, _odp_event_hdr_t *event_hdr[], int num);
@@ -71,7 +71,7 @@ static inline void *shm_pool_alloc_align(_odp_ishm_pool_t *pool, uint32_t size)
{
void *addr;
- addr = _odp_ishm_pool_alloc(pool, ROUNDUP_CACHE_LINE(size));
+ addr = _odp_ishm_pool_alloc(pool, _ODP_ROUNDUP_CACHE_LINE(size));
ODP_ASSERT(((uintptr_t)addr & (ODP_CACHE_LINE_SIZE - 1)) == 0);
return addr;
diff --git a/platform/linux-generic/include/odp_ring_internal.h b/platform/linux-generic/include/odp_ring_internal.h
index d11e81bf2..961e83448 100644
--- a/platform/linux-generic/include/odp_ring_internal.h
+++ b/platform/linux-generic/include/odp_ring_internal.h
@@ -15,12 +15,14 @@
extern "C" {
#endif
+#include <odp/api/align.h>
#include <odp/api/atomic.h>
#include <odp/api/cpu.h>
#include <odp/api/hints.h>
-#include <odp_align_internal.h>
+
#include <odp/api/plat/atomic_inlines.h>
#include <odp/api/plat/cpu_inlines.h>
+
#include <odp_ring_common.h>
/* Generic ring implementation
diff --git a/platform/linux-generic/include/odp_ring_mpmc_internal.h b/platform/linux-generic/include/odp_ring_mpmc_internal.h
index 473e69e90..6ed4dd4d1 100644
--- a/platform/linux-generic/include/odp_ring_mpmc_internal.h
+++ b/platform/linux-generic/include/odp_ring_mpmc_internal.h
@@ -11,10 +11,11 @@
extern "C" {
#endif
+#include <odp/api/align.h>
#include <odp/api/atomic.h>
#include <odp/api/cpu.h>
#include <odp/api/hints.h>
-#include <odp_align_internal.h>
+
#include <odp/api/plat/atomic_inlines.h>
#include <odp/api/plat/cpu_inlines.h>
diff --git a/platform/linux-generic/include/odp_ring_st_internal.h b/platform/linux-generic/include/odp_ring_st_internal.h
index 23b012d96..406d043b5 100644
--- a/platform/linux-generic/include/odp_ring_st_internal.h
+++ b/platform/linux-generic/include/odp_ring_st_internal.h
@@ -11,8 +11,8 @@
extern "C" {
#endif
+#include <odp/api/align.h>
#include <odp/api/hints.h>
-#include <odp_align_internal.h>
/* Basic ring for single thread usage. Operations must be synchronized by using
* locks (or other means), when multiple threads use the same ring. */
diff --git a/platform/linux-generic/include/odp_schedule_if.h b/platform/linux-generic/include/odp_schedule_if.h
index cec9c8bb8..d9ba165bc 100644
--- a/platform/linux-generic/include/odp_schedule_if.h
+++ b/platform/linux-generic/include/odp_schedule_if.h
@@ -131,6 +131,7 @@ typedef struct {
uint32_t lock_index);
void (*schedule_order_lock_start)(uint32_t lock_index);
void (*schedule_order_lock_wait)(uint32_t lock_index);
+ void (*schedule_order_wait)(void);
void (*schedule_print)(void);
} schedule_api_t;
diff --git a/platform/linux-generic/include/odp_schedule_scalable_ordered.h b/platform/linux-generic/include/odp_schedule_scalable_ordered.h
index 21c89bed2..be4894f73 100644
--- a/platform/linux-generic/include/odp_schedule_scalable_ordered.h
+++ b/platform/linux-generic/include/odp_schedule_scalable_ordered.h
@@ -9,11 +9,12 @@
#ifndef ODP_SCHEDULE_SCALABLE_ORDERED_H
#define ODP_SCHEDULE_SCALABLE_ORDERED_H
+#include <odp/api/align.h>
#include <odp/api/shared_memory.h>
-#include <odp_align_internal.h>
#include <odp_bitset.h>
#include <odp_event_internal.h>
+#include <odp_macros_internal.h>
#include <odp_ishmpool_internal.h>
/* High level functioning of reordering
@@ -68,7 +69,7 @@ typedef struct ODP_ALIGNED(sizeof(uint64_t)) hc {
* Should be at least one per CPU.
*/
#define RWIN_SIZE 32
-ODP_STATIC_ASSERT(CHECK_IS_POWER2(RWIN_SIZE), "RWIN_SIZE is not a power of 2");
+ODP_STATIC_ASSERT(_ODP_CHECK_IS_POWER2(RWIN_SIZE), "RWIN_SIZE is not a power of 2");
typedef struct reorder_context reorder_context_t;
diff --git a/platform/linux-generic/libodp-linux.pc.in b/platform/linux-generic/libodp-linux.pc.in
index 28c7ac49c..f9a339fb8 100644
--- a/platform/linux-generic/libodp-linux.pc.in
+++ b/platform/linux-generic/libodp-linux.pc.in
@@ -8,5 +8,5 @@ Description: The ODP packet processing engine
Version: @PKGCONFIG_VERSION@
Requires.private: libconfig@AARCH64CRYPTO_PKG@
Libs: -L${libdir} -l@ODP_LIB_NAME@ @ATOMIC_LIBS_NON_ABI_COMPAT@
-Libs.private: @OPENSSL_STATIC_LIBS@ @DPDK_LIBS@ @PCAP_LIBS@ @PTHREAD_LIBS@ @TIMER_LIBS@ -lpthread @ATOMIC_LIBS_ABI_COMPAT@
+Libs.private: @OPENSSL_STATIC_LIBS@ @DPDK_LIBS@ @PCAP_LIBS@ @PTHREAD_LIBS@ @TIMER_LIBS@ @LIBXDP_LIBS@ -lpthread @ATOMIC_LIBS_ABI_COMPAT@
Cflags: -I${includedir}
diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4
index 291cb2773..70a393f56 100644
--- a/platform/linux-generic/m4/configure.m4
+++ b/platform/linux-generic/m4/configure.m4
@@ -26,9 +26,10 @@ m4_include([platform/linux-generic/m4/odp_crypto.m4])
m4_include([platform/linux-generic/m4/odp_pcapng.m4])
m4_include([platform/linux-generic/m4/odp_netmap.m4])
m4_include([platform/linux-generic/m4/odp_dpdk.m4])
+m4_include([platform/linux-generic/m4/odp_xdp.m4])
ODP_SCHEDULER
-AS_VAR_APPEND([PLAT_DEP_LIBS], ["${ATOMIC_LIBS} ${AARCH64CRYPTO_LIBS} ${LIBCONFIG_LIBS} ${OPENSSL_LIBS} ${DPDK_LIBS_LT} ${LIBCLI_LIBS}"])
+AS_VAR_APPEND([PLAT_DEP_LIBS], ["${ATOMIC_LIBS} ${AARCH64CRYPTO_LIBS} ${LIBCONFIG_LIBS} ${OPENSSL_LIBS} ${DPDK_LIBS_LT} ${LIBCLI_LIBS} ${LIBXDP_LIBS}"])
# Add text to the end of configure with platform specific settings.
# Make sure it's aligned same as other lines in configure.ac.
diff --git a/platform/linux-generic/m4/odp_xdp.m4 b/platform/linux-generic/m4/odp_xdp.m4
new file mode 100644
index 000000000..2c6179df9
--- /dev/null
+++ b/platform/linux-generic/m4/odp_xdp.m4
@@ -0,0 +1,15 @@
+##########################################################################
+# Check for libxdp availability
+##########################################################################
+AC_ARG_ENABLE([xdp], AS_HELP_STRING([--enable-xdp],
+ [enable experimental XDP support for Packet I/O [default=disabled] (linux-generic)]))
+
+AS_IF([test "x$enable_xdp" = "xyes"], [
+ PKG_CHECK_MODULES([LIBXDP], [libxdp],
+ [
+ AC_DEFINE(_ODP_PKTIO_XDP, [1], [Define to 1 to enable xdp packet I/O support])
+ ],
+ [
+ AS_IF([test "x$enable_xdp" == "xyes"], [AC_MSG_ERROR([libxdp not found])])
+ ])
+])
diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c
index 2fdecbc51..90ebc8ae0 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -169,8 +169,10 @@ int odp_cls_capability(odp_cls_capability_t *capability)
capability->supported_terms.bit.ethtype_x = 1;
capability->supported_terms.bit.vlan_id_0 = 1;
capability->supported_terms.bit.vlan_id_x = 1;
+ capability->supported_terms.bit.vlan_pcp_0 = 1;
capability->supported_terms.bit.dmac = 1;
capability->supported_terms.bit.ip_proto = 1;
+ capability->supported_terms.bit.ip_dscp = 1;
capability->supported_terms.bit.udp_dport = 1;
capability->supported_terms.bit.udp_sport = 1;
capability->supported_terms.bit.tcp_dport = 1;
@@ -595,11 +597,8 @@ int odp_cos_with_l2_priority(odp_pktio_t pktio_in,
return 0;
}
-int odp_cos_with_l3_qos(odp_pktio_t pktio_in,
- uint32_t num_qos,
- uint8_t qos_table[],
- odp_cos_t cos_table[],
- odp_bool_t l3_preference)
+int ODP_DEPRECATE(odp_cos_with_l3_qos)(odp_pktio_t pktio_in, uint32_t num_qos, uint8_t qos_table[],
+ odp_cos_t cos_table[], odp_bool_t l3_preference)
{
pmr_l3_cos_t *l3_cos;
uint32_t i;
@@ -644,7 +643,11 @@ static int pmr_create_term(pmr_term_value_t *value,
value->range_term = param->range_term;
switch (term) {
+ case ODP_PMR_VLAN_PCP_0:
+ /* Fall through */
case ODP_PMR_IPPROTO:
+ /* Fall through */
+ case ODP_PMR_IP_DSCP:
size = 1;
break;
@@ -856,23 +859,50 @@ static inline int verify_pmr_packet_len(odp_packet_hdr_t *pkt_hdr,
return 0;
}
-static inline int verify_pmr_ip_proto(const uint8_t *pkt_addr,
- odp_packet_hdr_t *pkt_hdr,
- pmr_term_value_t *term_value)
+static inline int verify_pmr_ipv4_proto(const _odp_ipv4hdr_t *ipv4, pmr_term_value_t *term_value)
{
- const _odp_ipv4hdr_t *ip;
uint8_t proto;
- if (!pkt_hdr->p.input_flags.ipv4)
- return 0;
- ip = (const _odp_ipv4hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
- proto = ip->proto;
+ proto = ipv4->proto;
if (term_value->match.value == (proto & term_value->match.mask))
return 1;
return 0;
}
+static inline int verify_pmr_ipv6_next_hdr(const _odp_ipv6hdr_t *ipv6, pmr_term_value_t *term_value)
+{
+ uint8_t next_hdr;
+
+ next_hdr = ipv6->next_hdr;
+ if (term_value->match.value == (next_hdr & term_value->match.mask))
+ return 1;
+
+ return 0;
+}
+
+static inline int verify_pmr_ipv4_dscp(const _odp_ipv4hdr_t *ipv4, pmr_term_value_t *term_value)
+{
+ uint8_t dscp;
+
+ dscp = _ODP_IPV4HDR_DSCP(ipv4->tos);
+ if (term_value->match.value == (dscp & term_value->match.mask))
+ return 1;
+
+ return 0;
+}
+
+static inline int verify_pmr_ipv6_dscp(const _odp_ipv6hdr_t *ipv6, pmr_term_value_t *term_value)
+{
+ uint8_t dscp;
+
+ dscp = _ODP_IPV6HDR_DSCP(odp_be_to_cpu_32(ipv6->ver_tc_flow));
+ if (term_value->match.value == (dscp & term_value->match.mask))
+ return 1;
+
+ return 0;
+}
+
static inline int verify_pmr_ipv4_saddr(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
@@ -1095,6 +1125,28 @@ static inline int verify_pmr_vlan_id_x(const uint8_t *pkt_addr,
return 0;
}
+static inline int verify_pmr_vlan_pcp_0(const uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr,
+ pmr_term_value_t *term_value)
+{
+ const _odp_ethhdr_t *eth;
+ const _odp_vlanhdr_t *vlan;
+ uint16_t tci;
+ uint8_t pcp;
+
+ if (!packet_hdr_has_eth(pkt_hdr) || !pkt_hdr->p.input_flags.vlan)
+ return 0;
+
+ eth = (const _odp_ethhdr_t *)(pkt_addr + pkt_hdr->p.l2_offset);
+ vlan = (const _odp_vlanhdr_t *)(eth + 1);
+ tci = odp_be_to_cpu_16(vlan->tci);
+ pcp = tci >> _ODP_VLANHDR_PCP_SHIFT;
+
+ if (term_value->match.value == (pcp & term_value->match.mask))
+ return 1;
+
+ return 0;
+}
+
static inline int verify_pmr_ipsec_spi(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
@@ -1241,6 +1293,8 @@ static int verify_pmr(pmr_t *pmr, const uint8_t *pkt_addr,
int num_pmr;
int i;
pmr_term_value_t *term_value;
+ const _odp_ipv4hdr_t *ipv4 = NULL;
+ const _odp_ipv6hdr_t *ipv6 = NULL;
/* Locking is not required as PMR rules for in-flight packets
delivery during a PMR change is indeterminate*/
@@ -1249,6 +1303,11 @@ static int verify_pmr(pmr_t *pmr, const uint8_t *pkt_addr,
return 0;
num_pmr = pmr->s.num_pmr;
+ if (pkt_hdr->p.input_flags.ipv4)
+ ipv4 = (const _odp_ipv4hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
+ if (pkt_hdr->p.input_flags.ipv6)
+ ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
+
/* Iterate through list of PMR Term values in a pmr_t */
for (i = 0; i < num_pmr; i++) {
term_value = &pmr->s.pmr_term_value[i];
@@ -1277,15 +1336,36 @@ static int verify_pmr(pmr_t *pmr, const uint8_t *pkt_addr,
term_value))
pmr_failure = 1;
break;
+ case ODP_PMR_VLAN_PCP_0:
+ if (!verify_pmr_vlan_pcp_0(pkt_addr, pkt_hdr, term_value))
+ pmr_failure = 1;
+ break;
case ODP_PMR_DMAC:
if (!verify_pmr_dmac(pkt_addr, pkt_hdr,
term_value))
pmr_failure = 1;
break;
case ODP_PMR_IPPROTO:
- if (!verify_pmr_ip_proto(pkt_addr, pkt_hdr,
- term_value))
+ if (ipv4) {
+ if (!verify_pmr_ipv4_proto(ipv4, term_value))
+ pmr_failure = 1;
+ } else if (ipv6) {
+ if (!verify_pmr_ipv6_next_hdr(ipv6, term_value))
+ pmr_failure = 1;
+ } else {
pmr_failure = 1;
+ }
+ break;
+ case ODP_PMR_IP_DSCP:
+ if (ipv4) {
+ if (!verify_pmr_ipv4_dscp(ipv4, term_value))
+ pmr_failure = 1;
+ } else if (ipv6) {
+ if (!verify_pmr_ipv6_dscp(ipv6, term_value))
+ pmr_failure = 1;
+ } else {
+ pmr_failure = 1;
+ }
break;
case ODP_PMR_UDP_DPORT:
if (!verify_pmr_udp_dport(pkt_addr, pkt_hdr,
@@ -1381,12 +1461,18 @@ static const char *format_pmr_name(odp_cls_pmr_term_t pmr_term)
case ODP_PMR_VLAN_ID_X:
name = "PMR_VLAN_ID_X";
break;
+ case ODP_PMR_VLAN_PCP_0:
+ name = "PMR_VLAN_PCP_0";
+ break;
case ODP_PMR_DMAC:
name = "PMR_DMAC";
break;
case ODP_PMR_IPPROTO:
name = "PMR_IPPROTO";
break;
+ case ODP_PMR_IP_DSCP:
+ name = "PMR_IP_DSCP";
+ break;
case ODP_PMR_UDP_DPORT:
name = "PMR_UDP_DPORT";
break;
diff --git a/platform/linux-generic/odp_crypto_null.c b/platform/linux-generic/odp_crypto_null.c
index f276d4659..8eb2332a1 100644
--- a/platform/linux-generic/odp_crypto_null.c
+++ b/platform/linux-generic/odp_crypto_null.c
@@ -299,7 +299,6 @@ odp_crypto_operation(odp_crypto_op_param_t *param,
* We cannot fail since odp_crypto_op() has already processed
* the packet. Let's indicate error in the result instead.
*/
- packet_hdr(out_pkt)->p.flags.crypto_err = 1;
packet_result.ok = false;
}
@@ -496,7 +495,6 @@ int crypto_int(odp_packet_t pkt_in,
odp_bool_t allocated = false;
odp_packet_t out_pkt = *pkt_out;
odp_crypto_packet_result_t *op_result;
- odp_packet_hdr_t *pkt_hdr;
session = (odp_crypto_generic_session_t *)(intptr_t)param->session;
@@ -546,9 +544,6 @@ int crypto_int(odp_packet_t pkt_in,
op_result->auth_status.hw_err = ODP_CRYPTO_HW_ERR_NONE;
op_result->ok = true;
- pkt_hdr = packet_hdr(out_pkt);
- pkt_hdr->p.flags.crypto_err = !op_result->ok;
-
/* Synchronous, simply return results */
*pkt_out = out_pkt;
diff --git a/platform/linux-generic/odp_crypto_openssl.c b/platform/linux-generic/odp_crypto_openssl.c
index 6ff0ac041..9f0978b49 100644
--- a/platform/linux-generic/odp_crypto_openssl.c
+++ b/platform/linux-generic/odp_crypto_openssl.c
@@ -18,6 +18,7 @@
#include <odp/api/random.h>
#include <odp/api/plat/packet_inlines.h>
#include <odp/api/plat/thread_inlines.h>
+#include <odp_macros_internal.h>
#include <odp_packet_internal.h>
#include <odp/api/plat/queue_inlines.h>
#include <odp_global_data.h>
@@ -1013,7 +1014,7 @@ static inline int internal_crypt(EVP_CIPHER_CTX *ctx,
rc = EVP_update(ctx, in_addr, &out_len, in_addr, len);
if (odp_unlikely(rc != 1))
goto err;
- ODP_ASSERT(CHECK_IS_POWER2(block_len));
+ ODP_ASSERT(_ODP_CHECK_IS_POWER2(block_len));
buffered = len & (block_len - 1);
if (odp_unlikely(out_len + buffered != len))
goto err;
@@ -2531,7 +2532,6 @@ odp_crypto_operation(odp_crypto_op_param_t *param,
* We cannot fail since odp_crypto_op() has already processed
* the packet. Let's indicate error in the result instead.
*/
- packet_hdr(out_pkt)->p.flags.crypto_err = 1;
packet_result.ok = false;
}
@@ -2810,7 +2810,6 @@ int crypto_int(odp_packet_t pkt_in,
odp_bool_t allocated = false;
odp_packet_t out_pkt = *pkt_out;
odp_crypto_packet_result_t *op_result;
- odp_packet_hdr_t *pkt_hdr;
session = (odp_crypto_generic_session_t *)(intptr_t)param->session;
@@ -2873,9 +2872,6 @@ int crypto_int(odp_packet_t pkt_in,
(rc_cipher == ODP_CRYPTO_ALG_ERR_NONE) &&
(rc_auth == ODP_CRYPTO_ALG_ERR_NONE);
- pkt_hdr = packet_hdr(out_pkt);
- pkt_hdr->p.flags.crypto_err = !op_result->ok;
-
/* Synchronous, simply return results */
*pkt_out = out_pkt;
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c
index 29f0e4bcd..04b4b6aeb 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -5,19 +5,20 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <odp/api/byteorder.h>
#include <odp/api/ipsec.h>
#include <odp/api/chksum.h>
#include <odp/api/plat/packet_inlines.h>
-#include <odp/api/byteorder.h>
#include <odp/api/plat/byteorder_inlines.h>
+#include <odp/api/plat/queue_inlines.h>
#include <odp_global_data.h>
#include <odp_init_internal.h>
#include <odp_debug_internal.h>
+#include <odp_macros_internal.h>
#include <odp_packet_internal.h>
#include <odp_ipsec_internal.h>
-#include <odp/api/plat/queue_inlines.h>
#include <odp_classification_internal.h>
#include <odp_libconfig_internal.h>
#include <odp_schedule_if.h>
@@ -1099,7 +1100,7 @@ uint64_t ipsec_seq_no(ipsec_sa_t *ipsec_sa)
*/
static inline uint32_t ipsec_padded_len(uint32_t len, uint32_t pad_mask)
{
- ODP_ASSERT(CHECK_IS_POWER2(pad_mask + 1));
+ ODP_ASSERT(_ODP_CHECK_IS_POWER2(pad_mask + 1));
return (len + pad_mask) & ~pad_mask;
}
diff --git a/platform/linux-generic/odp_ipsec_sad.c b/platform/linux-generic/odp_ipsec_sad.c
index 4e4057ede..64d7b6fdf 100644
--- a/platform/linux-generic/odp_ipsec_sad.c
+++ b/platform/linux-generic/odp_ipsec_sad.c
@@ -10,16 +10,17 @@
#include <odp/api/random.h>
#include <odp/api/shared_memory.h>
+#include <odp/api/plat/atomic_inlines.h>
+#include <odp/api/plat/cpu_inlines.h>
+
#include <odp_config_internal.h>
#include <odp_init_internal.h>
#include <odp_debug_internal.h>
#include <odp_ipsec_internal.h>
+#include <odp_macros_internal.h>
#include <odp_ring_mpmc_internal.h>
#include <odp_global_data.h>
-#include <odp/api/plat/atomic_inlines.h>
-#include <odp/api/plat/cpu_inlines.h>
-
#include <string.h>
#include <inttypes.h>
@@ -430,7 +431,7 @@ static uint32_t esp_block_len_to_mask(uint32_t block_len)
if (block_len < 4)
block_len = 4;
- ODP_ASSERT(CHECK_IS_POWER2(block_len));
+ ODP_ASSERT(_ODP_CHECK_IS_POWER2(block_len));
return block_len - 1;
}
diff --git a/platform/linux-generic/odp_ishm.c b/platform/linux-generic/odp_ishm.c
index dea4d56f0..0f7c48f35 100644
--- a/platform/linux-generic/odp_ishm.c
+++ b/platform/linux-generic/odp_ishm.c
@@ -45,7 +45,6 @@
#include <odp_errno_define.h>
#include <odp_shm_internal.h>
#include <odp_debug_internal.h>
-#include <odp_align_internal.h>
#include <odp_fdserver_internal.h>
#include <odp_shm_internal.h>
#include <odp_ishmphy_internal.h>
diff --git a/platform/linux-generic/odp_ishmphy.c b/platform/linux-generic/odp_ishmphy.c
index 64eb2a732..efaf12c7b 100644
--- a/platform/linux-generic/odp_ishmphy.c
+++ b/platform/linux-generic/odp_ishmphy.c
@@ -14,7 +14,6 @@
#include <odp/api/system_info.h>
#include <odp/api/debug.h>
#include <odp_debug_internal.h>
-#include <odp_align_internal.h>
#include <odp_shm_internal.h>
#include <odp_ishmphy_internal.h>
diff --git a/platform/linux-generic/odp_ishmpool.c b/platform/linux-generic/odp_ishmpool.c
index 818b0a132..4186444fa 100644
--- a/platform/linux-generic/odp_ishmpool.c
+++ b/platform/linux-generic/odp_ishmpool.c
@@ -43,14 +43,17 @@
*/
#include <odp_posix_extensions.h>
+
#include <odp/api/spinlock.h>
#include <odp/api/align.h>
#include <odp/api/debug.h>
+
#include <odp_shm_internal.h>
#include <odp_debug_internal.h>
-#include <odp_align_internal.h>
+#include <odp_macros_internal.h>
#include <odp_shm_internal.h>
#include <odp_ishmpool_internal.h>
+
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -203,14 +206,14 @@ static pool_t *_odp_ishmbud_pool_create(const char *pool_name, int store_idx,
max_nb_bblock = (1 << (order - min_order));
/* space needed for the control area (padded to cache line size)*/
- control_sz = ROUNDUP_CACHE_LINE(sizeof(_odp_ishm_pool_ctrl_t));
+ control_sz = _ODP_ROUNDUP_CACHE_LINE(sizeof(_odp_ishm_pool_ctrl_t));
/* space needed for 'order' free bblock list heads: */
/* Note that only lists from min_order to order are really used.*/
- free_head_sz = ROUNDUP_CACHE_LINE(sizeof(void *) * (order + 1));
+ free_head_sz = _ODP_ROUNDUP_CACHE_LINE(sizeof(void *) * (order + 1));
/* space needed for order -i.e. size- storage of alloc'd bblock:*/
- saved_order_sz = ROUNDUP_CACHE_LINE(max_nb_bblock * sizeof(uint8_t));
+ saved_order_sz = _ODP_ROUNDUP_CACHE_LINE(max_nb_bblock * sizeof(uint8_t));
/* space needed for user area is 2^order bytes: */
user_sz = 1ULL << order;
@@ -455,7 +458,7 @@ static pool_t *_odp_ishmslab_pool_create(const char *pool_name, int store_idx,
nb_sblock = (size / elt_size) + ((size % elt_size) ? 1 : 0);
/* space needed for the control area (padded to cache line size)*/
- control_sz = ROUNDUP_CACHE_LINE(sizeof(_odp_ishm_pool_ctrl_t));
+ control_sz = _ODP_ROUNDUP_CACHE_LINE(sizeof(_odp_ishm_pool_ctrl_t));
/* space needed for user area is : */
user_sz = nb_sblock * elt_size;
diff --git a/platform/linux-generic/odp_name_table.c b/platform/linux-generic/odp_name_table.c
index a9ce6cad3..fbb35cf00 100644
--- a/platform/linux-generic/odp_name_table.c
+++ b/platform/linux-generic/odp_name_table.c
@@ -248,7 +248,7 @@ static uint32_t name_tbl_free_list_add(name_tbl_t *name_tbl,
name_tbl_id = name_tbl->base_id | first_idx;
entry_idx = first_idx;
- num_added = MIN(num_to_add, name_tbl->num_avail_to_add);
+ num_added = _ODP_MIN(num_to_add, name_tbl->num_avail_to_add);
if (num_added == 0)
return 0;
@@ -299,7 +299,7 @@ static int new_name_tbl_add(void)
name_tbls_idx = name_tbls.num_name_tbls;
num_entries = INITIAL_NAME_TBL_SIZE << name_tbls_idx;
new_name_tbl = name_tbl_alloc(name_tbls_idx, num_entries);
- name_tbl_free_list_add(new_name_tbl, MIN(num_entries, UINT32_C(256)));
+ name_tbl_free_list_add(new_name_tbl, _ODP_MIN(num_entries, UINT32_C(256)));
name_tbls.tbls[name_tbls_idx] = new_name_tbl;
name_tbls.avail_space_bit_mask |= 1 << name_tbls_idx;
@@ -389,7 +389,7 @@ static hash_tbl_entry_t make_hash_tbl_entry(name_tbl_entry_t *name_tbl_entry,
hash_tbl_entry_t hash_tbl_entry;
uint32_t new_entry_cnt;
- new_entry_cnt = MIN(entry_cnt + 1, UINT32_C(0x3F));
+ new_entry_cnt = _ODP_MIN(entry_cnt + 1, UINT32_C(0x3F));
hash_tbl_entry = (hash_tbl_entry_t)(uintptr_t)name_tbl_entry;
hash_tbl_entry &= ~0x3F;
hash_tbl_entry |= new_entry_cnt;
@@ -1008,7 +1008,7 @@ static uint32_t level2_hash_histo(secondary_hash_tbl_t *hash_tbl,
collisions = linked_list_len(name_tbl_entry);
}
- level2_histo[MIN(collisions, UINT32_C(256))]++;
+ level2_histo[_ODP_MIN(collisions, UINT32_C(256))]++;
total_collisions += collisions;
}
@@ -1040,7 +1040,7 @@ static uint32_t level1_hash_histo(secondary_hash_tbl_t *hash_tbl,
level2_histo);
}
- level1_histo[MIN(collisions, UINT32_C(256))]++;
+ level1_histo[_ODP_MIN(collisions, UINT32_C(256))]++;
total_collisions += collisions;
}
@@ -1150,7 +1150,7 @@ void _odp_int_name_tbl_stats_print(void)
memset(primary_hash_histo, 0, sizeof(primary_hash_histo));
for (idx = 0; idx < PRIMARY_HASH_TBL_SIZE; idx++) {
collisions =
- MIN(name_hash_tbl.hash_collisions[idx], UINT32_C(256));
+ _ODP_MIN(name_hash_tbl.hash_collisions[idx], UINT32_C(256));
primary_hash_histo[collisions]++;
}
diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c
index b0d0fc03c..07e9c2d4d 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -1241,7 +1241,7 @@ int odp_packet_align(odp_packet_t *pkt, uint32_t offset, uint32_t len,
if (seglen >= len) {
misalign = align <= 1 ? 0 :
- ROUNDUP_ALIGN(uaddr, align) - uaddr;
+ _ODP_ROUNDUP_ALIGN(uaddr, align) - uaddr;
if (misalign == 0)
return 0;
shift = align - misalign;
@@ -1251,7 +1251,7 @@ int odp_packet_align(odp_packet_t *pkt, uint32_t offset, uint32_t len,
shift = len - seglen;
uaddr -= shift;
misalign = align <= 1 ? 0 :
- ROUNDUP_ALIGN(uaddr, align) - uaddr;
+ _ODP_ROUNDUP_ALIGN(uaddr, align) - uaddr;
if (misalign)
shift += align - misalign;
}
diff --git a/platform/linux-generic/odp_pcapng.c b/platform/linux-generic/odp_pcapng.c
index 6bdd1fd69..2a4b7ad04 100644
--- a/platform/linux-generic/odp_pcapng.c
+++ b/platform/linux-generic/odp_pcapng.c
@@ -130,8 +130,7 @@ static void pcapng_drain_fifo(int fd)
static void inotify_event_handle(pktio_entry_t *entry, int qidx,
struct inotify_event *event)
{
- int mtu = MAX(odp_pktin_maxlen(entry->s.handle),
- odp_pktout_maxlen(entry->s.handle));
+ int mtu = _ODP_MAX(odp_pktin_maxlen(entry->s.handle), odp_pktout_maxlen(entry->s.handle));
if (event->mask & IN_OPEN) {
int ret;
@@ -173,8 +172,7 @@ static void get_pcapng_fifo_name(char *pcapng_entry, size_t len,
static int get_qidx_from_fifo(pktio_entry_t *entry, char *name)
{
- unsigned int max_queue =
- MAX(entry->s.num_in_queue, entry->s.num_out_queue);
+ unsigned int max_queue = _ODP_MAX(entry->s.num_in_queue, entry->s.num_out_queue);
unsigned int i;
for (i = 0; i < max_queue; i++) {
@@ -291,8 +289,7 @@ int _odp_pcapng_start(pktio_entry_t *entry)
int ret = -1, fd;
pthread_attr_t attr;
unsigned int i;
- unsigned int max_queue =
- MAX(entry->s.num_in_queue, entry->s.num_out_queue);
+ unsigned int max_queue = _ODP_MAX(entry->s.num_in_queue, entry->s.num_out_queue);
int fifo_sz;
fifo_sz = get_fifo_max_size();
@@ -396,8 +393,7 @@ void _odp_pcapng_stop(pktio_entry_t *entry)
{
int ret;
unsigned int i;
- unsigned int max_queue =
- MAX(entry->s.num_in_queue, entry->s.num_out_queue);
+ unsigned int max_queue = _ODP_MAX(entry->s.num_in_queue, entry->s.num_out_queue);
odp_spinlock_lock(&pcapng_gbl->lock);
@@ -528,7 +524,7 @@ int _odp_pcapng_write_pkts(pktio_entry_t *entry, int qidx,
NULL);
if (block_len + sizeof(epb[i]) +
- ROUNDUP_ALIGN(seg_len, PCAPNG_DATA_ALIGN) +
+ _ODP_ROUNDUP_ALIGN(seg_len, PCAPNG_DATA_ALIGN) +
sizeof(uint32_t) > PIPE_BUF) {
wlen = write_fifo(fd, packet_iov, iovcnt);
if (wlen > 0) {
@@ -539,7 +535,7 @@ int _odp_pcapng_write_pkts(pktio_entry_t *entry, int qidx,
}
epb[i].block_type = PCAPNG_BLOCK_TYPE_EPB;
epb[i].block_total_length = sizeof(epb[i]) +
- ROUNDUP_ALIGN(seg_len, PCAPNG_DATA_ALIGN) +
+ _ODP_ROUNDUP_ALIGN(seg_len, PCAPNG_DATA_ALIGN) +
PCAPNG_DATA_ALIGN;
epb[i].interface_idx = 0;
epb[i].timestamp_high =
@@ -556,8 +552,7 @@ int _odp_pcapng_write_pkts(pktio_entry_t *entry, int qidx,
/* data */
packet_iov[iovcnt].iov_base = buf;
- packet_iov[iovcnt].iov_len =
- ROUNDUP_ALIGN(seg_len, PCAPNG_DATA_ALIGN);
+ packet_iov[iovcnt].iov_len = _ODP_ROUNDUP_ALIGN(seg_len, PCAPNG_DATA_ALIGN);
block_len += packet_iov[iovcnt].iov_len;
iovcnt++;
diff --git a/platform/linux-generic/odp_pkt_queue.c b/platform/linux-generic/odp_pkt_queue.c
index 81ae334c1..e977efc24 100644
--- a/platform/linux-generic/odp_pkt_queue.c
+++ b/platform/linux-generic/odp_pkt_queue.c
@@ -125,7 +125,7 @@ static int pkt_queue_free_list_add(queue_pool_t *pool,
}
/* Now add as many queue_blks to the free list as... */
- blks_to_add = MIN(num_blks - start_idx, num_queue_blks);
+ blks_to_add = _ODP_MIN(num_blks - start_idx, num_queue_blks);
queue_blk = &queue_blks->blks[start_idx];
for (cnt = 1; cnt <= blks_to_add; cnt++) {
queue_blk->next_queue_blk_idx = start_idx + cnt;
@@ -223,7 +223,7 @@ _odp_int_queue_pool_t _odp_queue_pool_create(uint32_t max_num_queues,
/* Initialize the queue_blk_tbl_sizes array based upon the
* max_queued_pkts.
*/
- max_queued_pkts = MAX(max_queued_pkts, 64 * UINT32_C(1024));
+ max_queued_pkts = _ODP_MAX(max_queued_pkts, 64 * UINT32_C(1024));
queue_region_desc_init(pool, 0, max_queued_pkts / 4);
queue_region_desc_init(pool, 1, max_queued_pkts / 64);
queue_region_desc_init(pool, 2, max_queued_pkts / 64);
@@ -235,7 +235,7 @@ _odp_int_queue_pool_t _odp_queue_pool_create(uint32_t max_num_queues,
/* Now allocate the first queue_blk_tbl and add its blks to the free
* list. Replenish the queue_blk_t free list.
*/
- initial_free_list_size = MIN(64 * UINT32_C(1024), max_queued_pkts / 4);
+ initial_free_list_size = _ODP_MIN(64 * UINT32_C(1024), max_queued_pkts / 4);
rc = pkt_queue_free_list_add(pool, initial_free_list_size);
if (rc < 0) {
free(pool->queue_num_tbl);
diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
index defdeb4fb..739665cb9 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -15,9 +15,9 @@
#include <odp_pool_internal.h>
#include <odp_init_internal.h>
#include <odp_packet_internal.h>
-#include <odp_packet_dpdk.h>
#include <odp_config_internal.h>
#include <odp_debug_internal.h>
+#include <odp_macros_internal.h>
#include <odp_ring_ptr_internal.h>
#include <odp_global_data.h>
#include <odp_libconfig_internal.h>
@@ -63,6 +63,8 @@ typedef struct pool_local_t {
} pool_local_t;
+extern const _odp_pool_mem_src_ops_t * const _odp_pool_mem_src_ops[];
+
pool_global_t *_odp_pool_glb;
static __thread pool_local_t local;
@@ -239,7 +241,7 @@ static int read_config_file(pool_global_t *pool_glb)
if (val == 0)
align = ODP_CACHE_LINE_SIZE;
- if (!CHECK_IS_POWER2(align)) {
+ if (!_ODP_CHECK_IS_POWER2(align)) {
ODP_ERR("Not a power of two: %s = %i\n", str, val);
return -1;
}
@@ -257,7 +259,7 @@ static int read_config_file(pool_global_t *pool_glb)
if (val == 0)
align = ODP_CACHE_LINE_SIZE;
- if (!CHECK_IS_POWER2(align)) {
+ if (!_ODP_CHECK_IS_POWER2(align)) {
ODP_ERR("Not a power of two: %s = %i\n", str, val);
return -1;
}
@@ -617,7 +619,7 @@ static int reserve_uarea(pool_t *pool, uint32_t uarea_size, uint32_t num_pkt, ui
sprintf(uarea_name, "pool_%03i_uarea_%s", pool->pool_idx, pool->name);
pool->param_uarea_size = uarea_size;
- pool->uarea_size = ROUNDUP_CACHE_LINE(uarea_size);
+ pool->uarea_size = _ODP_ROUNDUP_CACHE_LINE(uarea_size);
pool->uarea_shm_size = num_pkt * (uint64_t)pool->uarea_size;
shm = odp_shm_reserve(uarea_name, pool->uarea_shm_size, ODP_PAGE_SIZE, shmflags);
@@ -630,6 +632,26 @@ static int reserve_uarea(pool_t *pool, uint32_t uarea_size, uint32_t num_pkt, ui
return 0;
}
+static void set_mem_src_ops(pool_t *pool)
+{
+ odp_bool_t is_active_found = false;
+
+ pool->mem_src_ops = NULL;
+
+ for (int i = 0; _odp_pool_mem_src_ops[i]; i++) {
+ if (!is_active_found) {
+ if (_odp_pool_mem_src_ops[i]->is_active()) {
+ is_active_found = true;
+ pool->mem_src_ops = _odp_pool_mem_src_ops[i];
+ ODP_DBG("Packet pool as a memory source for: %s\n",
+ pool->mem_src_ops->name);
+ }
+ } else if (_odp_pool_mem_src_ops[i]->is_active()) {
+ _odp_pool_mem_src_ops[i]->force_disable();
+ }
+ }
+}
+
/* Create pool according to params. Actual type of the pool is type_2, which is recorded for pool
* info calls. */
odp_pool_t _odp_pool_create(const char *name, const odp_pool_param_t *params,
@@ -659,7 +681,7 @@ odp_pool_t _odp_pool_create(const char *name, const odp_pool_param_t *params,
uint32_t align_req = params->pkt.align;
if (align_req &&
- (!CHECK_IS_POWER2(align_req) ||
+ (!_ODP_CHECK_IS_POWER2(align_req) ||
align_req > _odp_pool_glb->config.pkt_base_align)) {
ODP_ERR("Bad align requirement\n");
return ODP_POOL_INVALID;
@@ -676,7 +698,7 @@ odp_pool_t _odp_pool_create(const char *name, const odp_pool_param_t *params,
/* Validate requested buffer alignment */
if (align > ODP_CONFIG_BUFFER_ALIGN_MAX ||
- align != ROUNDDOWN_POWER2(align, align)) {
+ align != _ODP_ROUNDDOWN_POWER2(align, align)) {
ODP_ERR("Bad align requirement\n");
return ODP_POOL_INVALID;
}
@@ -773,26 +795,29 @@ odp_pool_t _odp_pool_create(const char *name, const odp_pool_param_t *params,
pool->type_2 = type_2;
pool->params = *params;
pool->block_offset = 0;
+ set_mem_src_ops(pool);
if (type == ODP_POOL_PACKET) {
- uint32_t dpdk_obj_size;
+ uint32_t adj_size;
- hdr_size = ROUNDUP_CACHE_LINE(sizeof(odp_packet_hdr_t));
+ hdr_size = _ODP_ROUNDUP_CACHE_LINE(sizeof(odp_packet_hdr_t));
block_size = hdr_size + align + headroom + seg_len + tailroom;
- /* Calculate extra space required for storing DPDK objects and
- * mbuf headers. NOP if no DPDK pktio used or zero-copy mode is
- * disabled. */
- dpdk_obj_size = _odp_dpdk_pool_obj_size(pool, block_size);
- if (!dpdk_obj_size) {
- ODP_ERR("Calculating DPDK mempool obj size failed\n");
- return ODP_POOL_INVALID;
- }
- if (dpdk_obj_size != block_size) {
- shmflags |= ODP_SHM_HP;
- block_size = dpdk_obj_size;
- } else {
- block_size = ROUNDUP_CACHE_LINE(block_size);
+ adj_size = block_size;
+
+ if (pool->mem_src_ops && pool->mem_src_ops->adjust_size) {
+ pool->mem_src_ops->adjust_size(pool->mem_src_data, &adj_size,
+ &pool->block_offset, &shmflags);
+
+ if (!adj_size) {
+ ODP_ERR("Calculating adjusted block size failed\n");
+ return ODP_POOL_INVALID;
+ }
}
+
+ if (adj_size != block_size)
+ block_size = adj_size;
+ else
+ block_size = _ODP_ROUNDUP_CACHE_LINE(block_size);
} else {
/* Header size is rounded up to cache line size, so the
* following data can be cache line aligned without extra
@@ -801,13 +826,13 @@ odp_pool_t _odp_pool_create(const char *name, const odp_pool_param_t *params,
align - ODP_CACHE_LINE_SIZE : 0;
if (type == ODP_POOL_BUFFER)
- hdr_size = ROUNDUP_CACHE_LINE(sizeof(odp_buffer_hdr_t));
+ hdr_size = _ODP_ROUNDUP_CACHE_LINE(sizeof(odp_buffer_hdr_t));
else if (type == ODP_POOL_TIMEOUT)
- hdr_size = ROUNDUP_CACHE_LINE(sizeof(odp_timeout_hdr_t));
+ hdr_size = _ODP_ROUNDUP_CACHE_LINE(sizeof(odp_timeout_hdr_t));
else
- hdr_size = ROUNDUP_CACHE_LINE(sizeof(odp_event_vector_hdr_t));
+ hdr_size = _ODP_ROUNDUP_CACHE_LINE(sizeof(odp_event_vector_hdr_t));
- block_size = ROUNDUP_CACHE_LINE(hdr_size + align_pad + seg_len);
+ block_size = _ODP_ROUNDUP_CACHE_LINE(hdr_size + align_pad + seg_len);
}
/* Allocate extra memory for skipping packet buffers which cross huge
@@ -823,7 +848,7 @@ odp_pool_t _odp_pool_create(const char *name, const odp_pool_param_t *params,
if (num + 1 <= RING_SIZE_MIN)
ring_size = RING_SIZE_MIN;
else
- ring_size = ROUNDUP_POWER2_U32(num + 1);
+ ring_size = _ODP_ROUNDUP_POWER2_U32(num + 1);
pool->ring_mask = ring_size - 1;
pool->num = num;
@@ -835,8 +860,6 @@ odp_pool_t _odp_pool_create(const char *name, const odp_pool_param_t *params,
pool->tailroom = tailroom;
pool->block_size = block_size;
pool->shm_size = (num + num_extra) * (uint64_t)block_size;
- pool->ext_desc = NULL;
- pool->ext_destroy = NULL;
set_pool_cache_size(pool, cache_size);
@@ -863,12 +886,18 @@ odp_pool_t _odp_pool_create(const char *name, const odp_pool_param_t *params,
ring_ptr_init(&pool->ring->hdr);
init_buffers(pool);
- /* Create zero-copy DPDK memory pool. NOP if zero-copy is disabled. */
- if (type == ODP_POOL_PACKET && _odp_dpdk_pool_create(pool)) {
- ODP_ERR("Creating DPDK packet pool failed\n");
+ if (type == ODP_POOL_PACKET && pool->mem_src_ops && pool->mem_src_ops->bind &&
+ pool->mem_src_ops->bind(pool->mem_src_data, pool)) {
+ ODP_ERR("Binding pool as memory source failed\n");
goto error;
}
+ /* Total ops utilizes alloc_ops and free_ops counters */
+ if (pool->params.stats.bit.total_ops) {
+ pool->params.stats.bit.alloc_ops = 1;
+ pool->params.stats.bit.free_ops = 1;
+ }
+
/* Reset pool stats */
odp_atomic_init_u64(&pool->stats.alloc_ops, 0);
odp_atomic_init_u64(&pool->stats.alloc_fails, 0);
@@ -1074,12 +1103,8 @@ int odp_pool_destroy(odp_pool_t pool_hdl)
return -1;
}
- /* Destroy external DPDK mempool */
- if (pool->ext_destroy) {
- pool->ext_destroy(pool->ext_desc);
- pool->ext_destroy = NULL;
- pool->ext_desc = NULL;
- }
+ if (pool->type == ODP_POOL_PACKET && pool->mem_src_ops && pool->mem_src_ops->unbind)
+ pool->mem_src_ops->unbind(pool->mem_src_data);
/* Make sure local caches are empty */
for (i = 0; i < ODP_THREAD_COUNT_MAX; i++)
@@ -1369,7 +1394,7 @@ int odp_pool_capability(odp_pool_capability_t *capa)
supported_stats.bit.alloc_ops = CONFIG_POOL_STATISTICS;
supported_stats.bit.alloc_fails = CONFIG_POOL_STATISTICS;
supported_stats.bit.free_ops = CONFIG_POOL_STATISTICS;
- supported_stats.bit.total_ops = 0;
+ supported_stats.bit.total_ops = CONFIG_POOL_STATISTICS;
supported_stats.bit.cache_available = 1;
supported_stats.bit.cache_alloc_ops = CONFIG_POOL_STATISTICS;
supported_stats.bit.cache_free_ops = CONFIG_POOL_STATISTICS;
@@ -1452,6 +1477,8 @@ void odp_pool_print(odp_pool_t pool_hdl)
ODP_PRINT(" uarea base addr %p\n", (void *)pool->uarea_base_addr);
ODP_PRINT(" cache size %u\n", pool->cache_size);
ODP_PRINT(" burst size %u\n", pool->burst_size);
+ ODP_PRINT(" mem src %s\n",
+ pool->mem_src_ops ? pool->mem_src_ops->name : "(none)");
ODP_PRINT("\n");
}
@@ -1574,6 +1601,9 @@ int odp_pool_stats(odp_pool_t pool_hdl, odp_pool_stats_t *stats)
if (pool->params.stats.bit.free_ops)
stats->free_ops = odp_atomic_load_u64(&pool->stats.free_ops);
+ if (pool->params.stats.bit.total_ops)
+ stats->total_ops = stats->alloc_ops + stats->free_ops;
+
if (pool->params.stats.bit.cache_available)
stats->cache_available = cache_total_available(pool);
@@ -1798,7 +1828,7 @@ odp_pool_t odp_pool_ext_create(const char *name, const odp_pool_ext_param_t *par
if (num_buf + 1 <= RING_SIZE_MIN)
ring_size = RING_SIZE_MIN;
else
- ring_size = ROUNDUP_POWER2_U32(num_buf + 1);
+ ring_size = _ODP_ROUNDUP_POWER2_U32(num_buf + 1);
pool->ring_mask = ring_size - 1;
pool->type = param->type;
diff --git a/platform/linux-generic/odp_pool_mem_src_ops.c b/platform/linux-generic/odp_pool_mem_src_ops.c
new file mode 100644
index 000000000..2f8dc2078
--- /dev/null
+++ b/platform/linux-generic/odp_pool_mem_src_ops.c
@@ -0,0 +1,22 @@
+/* Copyright (c) 2022, Nokia
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/autoheader_internal.h>
+#include <odp_pool_internal.h>
+
+extern const _odp_pool_mem_src_ops_t _odp_pool_dpdk_mem_src_ops;
+extern const _odp_pool_mem_src_ops_t _odp_pool_sock_xdp_mem_src_ops;
+
+/* List of available ODP packet pool memory source operations. Array must be NULL terminated */
+const _odp_pool_mem_src_ops_t * const _odp_pool_mem_src_ops[] = {
+#ifdef _ODP_PKTIO_DPDK
+ &_odp_pool_dpdk_mem_src_ops,
+#endif
+#ifdef _ODP_PKTIO_XDP
+ &_odp_pool_sock_xdp_mem_src_ops,
+#endif
+ NULL
+};
diff --git a/platform/linux-generic/odp_queue_basic.c b/platform/linux-generic/odp_queue_basic.c
index 5155bae4b..9a1abfd3b 100644
--- a/platform/linux-generic/odp_queue_basic.c
+++ b/platform/linux-generic/odp_queue_basic.c
@@ -28,6 +28,7 @@
#include <odp_global_data.h>
#include <odp_queue_basic_internal.h>
#include <odp_event_internal.h>
+#include <odp_macros_internal.h>
#include <odp/api/plat/ticketlock_inlines.h>
#define LOCK(queue_ptr) odp_ticketlock_lock(&((queue_ptr)->s.lock))
@@ -77,7 +78,7 @@ static int read_config_file(queue_global_t *_odp_queue_glb)
val_u32 = val;
if (val_u32 > MAX_QUEUE_SIZE || val_u32 < MIN_QUEUE_SIZE ||
- !CHECK_IS_POWER2(val_u32)) {
+ !_ODP_CHECK_IS_POWER2(val_u32)) {
ODP_ERR("Bad value %s = %u\n", str, val_u32);
return -1;
}
@@ -95,7 +96,7 @@ static int read_config_file(queue_global_t *_odp_queue_glb)
if (val_u32 > _odp_queue_glb->config.max_queue_size ||
val_u32 < MIN_QUEUE_SIZE ||
- !CHECK_IS_POWER2(val_u32)) {
+ !_ODP_CHECK_IS_POWER2(val_u32)) {
ODP_ERR("Bad value %s = %u\n", str, val_u32);
return -1;
}
@@ -1039,7 +1040,7 @@ static int queue_init(queue_entry_t *queue, const char *name,
queue_size = MIN_QUEUE_SIZE;
/* Round up if not already a power of two */
- queue_size = ROUNDUP_POWER2_U32(queue_size);
+ queue_size = _ODP_ROUNDUP_POWER2_U32(queue_size);
if (queue_size > _odp_queue_glb->config.max_queue_size) {
ODP_ERR("Too large queue size %u\n", queue_size);
diff --git a/platform/linux-generic/odp_queue_scalable.c b/platform/linux-generic/odp_queue_scalable.c
index c92ebeddd..881dbb985 100644
--- a/platform/linux-generic/odp_queue_scalable.c
+++ b/platform/linux-generic/odp_queue_scalable.c
@@ -104,7 +104,7 @@ static int queue_init(queue_entry_t *queue, const char *name,
sched_elem = &queue->s.sched_elem;
ring_size = param->size > 0 ?
- ROUNDUP_POWER2_U32(param->size) : CONFIG_SCAL_QUEUE_SIZE;
+ _ODP_ROUNDUP_POWER2_U32(param->size) : CONFIG_SCAL_QUEUE_SIZE;
strncpy(queue->s.name, name ? name : "", ODP_QUEUE_NAME_LEN - 1);
queue->s.name[ODP_QUEUE_NAME_LEN - 1] = 0;
memcpy(&queue->s.param, param, sizeof(odp_queue_param_t));
@@ -529,7 +529,7 @@ static inline int _odp_queue_enq(sched_elem_t *q,
*/
old_read = __atomic_load_n(&q->prod_read, __ATOMIC_ACQUIRE);
- actual = MIN(num, (int)((mask + 1) - (old_write - old_read)));
+ actual = _ODP_MIN(num, (int)((mask + 1) - (old_write - old_read)));
if (odp_unlikely(actual <= 0))
return 0;
@@ -591,7 +591,7 @@ int _odp_queue_enq_sp(sched_elem_t *q,
old_write = q->prod_write;
/* Consumer does store-release prod_read, we need load-acquire */
old_read = __atomic_load_n(&q->prod_read, __ATOMIC_ACQUIRE);
- actual = MIN(num, (int)((mask + 1) - (old_write - old_read)));
+ actual = _ODP_MIN(num, (int)((mask + 1) - (old_write - old_read)));
if (odp_unlikely(actual <= 0))
return 0;
@@ -704,7 +704,7 @@ int _odp_queue_deq_sc(sched_elem_t *q, odp_event_t *evp, int num)
old_read = q->cons_read;
/* Producer does store-release cons_write, we need load-acquire */
old_write = __atomic_load_n(&q->cons_write, __ATOMIC_ACQUIRE);
- actual = MIN(num, (int)(old_write - old_read));
+ actual = _ODP_MIN(num, (int)(old_write - old_read));
if (odp_unlikely(actual <= 0))
return 0;
@@ -757,7 +757,7 @@ int _odp_queue_deq(sched_elem_t *q, _odp_event_hdr_t *event_hdr[], int num)
/* Prefetch ring buffer array */
__builtin_prefetch(&q->cons_ring[old_read & mask], 0, 0);
- actual = MIN(num, (int)(old_write - old_read));
+ actual = _ODP_MIN(num, (int)(old_write - old_read));
if (odp_unlikely(actual <= 0))
return 0;
diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c
index 3b22a5bb6..b6952bf1f 100644
--- a/platform/linux-generic/odp_schedule_basic.c
+++ b/platform/linux-generic/odp_schedule_basic.c
@@ -27,7 +27,6 @@
#include <odp/api/cpu.h>
#include <odp/api/thrmask.h>
#include <odp_config_internal.h>
-#include <odp_align_internal.h>
#include <odp/api/sync.h>
#include <odp/api/packet_io.h>
#include <odp_ring_u32_internal.h>
@@ -37,6 +36,7 @@
#include <odp/api/plat/queue_inlines.h>
#include <odp_global_data.h>
#include <odp_event_internal.h>
+#include <odp_macros_internal.h>
#include <string.h>
@@ -94,11 +94,11 @@ ODP_STATIC_ASSERT((QUEUE_LOAD * CONFIG_MAX_SCHED_QUEUES) < UINT32_MAX, "Load_val
#define MAX_RING_SIZE CONFIG_MAX_SCHED_QUEUES
/* For best performance, the number of queues should be a power of two. */
-ODP_STATIC_ASSERT(CHECK_IS_POWER2(CONFIG_MAX_SCHED_QUEUES),
+ODP_STATIC_ASSERT(_ODP_CHECK_IS_POWER2(CONFIG_MAX_SCHED_QUEUES),
"Number_of_queues_is_not_power_of_two");
/* Ring size must be power of two, so that mask can be used. */
-ODP_STATIC_ASSERT(CHECK_IS_POWER2(MAX_RING_SIZE),
+ODP_STATIC_ASSERT(_ODP_CHECK_IS_POWER2(MAX_RING_SIZE),
"Ring_size_is_not_power_of_two");
/* Thread ID is saved into uint16_t variable */
@@ -289,7 +289,7 @@ ODP_STATIC_ASSERT(MAX_SPREAD <= 256, "Spread_does_not_fit_8_bits");
ODP_STATIC_ASSERT(CONFIG_QUEUE_MAX_ORD_LOCKS <= 256,
"Ordered_lock_count_does_not_fit_8_bits");
ODP_STATIC_ASSERT(NUM_PKTIO <= 256, "Pktio_index_does_not_fit_8_bits");
-ODP_STATIC_ASSERT(CHECK_IS_POWER2(GRP_WEIGHT_TBL_SIZE), "Not_power_of_2");
+ODP_STATIC_ASSERT(_ODP_CHECK_IS_POWER2(GRP_WEIGHT_TBL_SIZE), "Not_power_of_2");
/* Global scheduler context */
static sched_global_t *sched;
@@ -503,7 +503,7 @@ static int schedule_init_global(void)
num_rings = sched->config.num_spread;
}
- ring_size = ROUNDUP_POWER2_U32(ring_size);
+ ring_size = _ODP_ROUNDUP_POWER2_U32(ring_size);
ODP_ASSERT(ring_size <= MAX_RING_SIZE);
sched->ring_mask = ring_size - 1;
@@ -1979,6 +1979,7 @@ static int schedule_capability(odp_schedule_capability_t *capa)
capa->max_queues = sched->max_queues;
capa->max_queue_size = _odp_queue_glb->config.max_queue_size;
capa->max_flow_id = BUF_HDR_MAX_FLOW_ID;
+ capa->order_wait = ODP_SUPPORT_YES;
return 0;
}
@@ -2117,5 +2118,6 @@ const schedule_api_t _odp_schedule_basic_api = {
.schedule_order_unlock_lock = schedule_order_unlock_lock,
.schedule_order_lock_start = schedule_order_lock_start,
.schedule_order_lock_wait = schedule_order_lock_wait,
+ .schedule_order_wait = order_lock,
.schedule_print = schedule_print
};
diff --git a/platform/linux-generic/odp_schedule_if.c b/platform/linux-generic/odp_schedule_if.c
index 3b908ea87..564153137 100644
--- a/platform/linux-generic/odp_schedule_if.c
+++ b/platform/linux-generic/odp_schedule_if.c
@@ -203,6 +203,11 @@ void odp_schedule_order_lock_wait(uint32_t lock_index)
_odp_sched_api->schedule_order_lock_wait(lock_index);
}
+void odp_schedule_order_wait(void)
+{
+ _odp_sched_api->schedule_order_wait();
+}
+
void odp_schedule_print(void)
{
_odp_sched_api->schedule_print();
diff --git a/platform/linux-generic/odp_schedule_scalable.c b/platform/linux-generic/odp_schedule_scalable.c
index 7482d776d..66cb66315 100644
--- a/platform/linux-generic/odp_schedule_scalable.c
+++ b/platform/linux-generic/odp_schedule_scalable.c
@@ -24,13 +24,13 @@
#include <odp_shm_internal.h>
#include <odp_ishmpool_internal.h>
-#include <odp_align_internal.h>
#include <odp/api/plat/cpu_inlines.h>
#include <odp_llqueue.h>
#include <odp_queue_scalable_internal.h>
#include <odp_schedule_if.h>
#include <odp_bitset.h>
#include <odp_event_internal.h>
+#include <odp_macros_internal.h>
#include <odp_packet_io_internal.h>
#include <odp_timer_internal.h>
@@ -46,7 +46,7 @@
#define FLAG_PKTIN 0x80
-ODP_STATIC_ASSERT(CHECK_IS_POWER2(CONFIG_MAX_SCHED_QUEUES),
+ODP_STATIC_ASSERT(_ODP_CHECK_IS_POWER2(CONFIG_MAX_SCHED_QUEUES),
"Number_of_queues_is_not_power_of_two");
#define SCHED_GROUP_JOIN 0
@@ -2167,6 +2167,7 @@ static int schedule_capability(odp_schedule_capability_t *capa)
capa->max_prios = schedule_num_prio();
capa->max_queues = CONFIG_MAX_SCHED_QUEUES;
capa->max_queue_size = 0;
+ capa->order_wait = ODP_SUPPORT_YES;
return 0;
}
@@ -2233,5 +2234,6 @@ const schedule_api_t _odp_schedule_scalable_api = {
.schedule_order_unlock_lock = schedule_order_unlock_lock,
.schedule_order_lock_start = schedule_order_lock_start,
.schedule_order_lock_wait = schedule_order_lock_wait,
+ .schedule_order_wait = order_lock,
.schedule_print = schedule_print
};
diff --git a/platform/linux-generic/odp_schedule_sp.c b/platform/linux-generic/odp_schedule_sp.c
index 558c3f4fe..11564d32b 100644
--- a/platform/linux-generic/odp_schedule_sp.c
+++ b/platform/linux-generic/odp_schedule_sp.c
@@ -24,9 +24,9 @@
#include <odp_schedule_if.h>
#include <odp_debug_internal.h>
-#include <odp_align_internal.h>
#include <odp_config_internal.h>
#include <odp_event_internal.h>
+#include <odp_macros_internal.h>
#include <odp_ring_u32_internal.h>
#include <odp_timer_internal.h>
#include <odp_queue_basic_internal.h>
@@ -53,11 +53,11 @@
#define GROUP_PKTIN GROUP_ALL
/* Maximum number of commands: one priority/group for all queues and pktios */
-#define RING_SIZE (ROUNDUP_POWER2_U32(NUM_QUEUE + NUM_PKTIO))
+#define RING_SIZE (_ODP_ROUNDUP_POWER2_U32(NUM_QUEUE + NUM_PKTIO))
#define RING_MASK (RING_SIZE - 1)
/* Ring size must be power of two */
-ODP_STATIC_ASSERT(CHECK_IS_POWER2(RING_SIZE),
+ODP_STATIC_ASSERT(_ODP_CHECK_IS_POWER2(RING_SIZE),
"Ring_size_is_not_power_of_two");
ODP_STATIC_ASSERT(NUM_ORDERED_LOCKS <= CONFIG_QUEUE_MAX_ORD_LOCKS,
@@ -80,7 +80,7 @@ struct sched_cmd_s {
typedef struct ODP_ALIGNED_CACHE sched_cmd_t {
struct sched_cmd_s s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct sched_cmd_s)) -
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(struct sched_cmd_s)) -
sizeof(struct sched_cmd_s)];
} sched_cmd_t;
@@ -1119,5 +1119,6 @@ const schedule_api_t _odp_schedule_sp_api = {
.schedule_order_unlock_lock = schedule_order_unlock_lock,
.schedule_order_lock_start = schedule_order_lock_start,
.schedule_order_lock_wait = schedule_order_lock_wait,
+ .schedule_order_wait = order_lock,
.schedule_print = schedule_print
};
diff --git a/platform/linux-generic/odp_stash.c b/platform/linux-generic/odp_stash.c
index 9dbc8cc26..e12f1aed3 100644
--- a/platform/linux-generic/odp_stash.c
+++ b/platform/linux-generic/odp_stash.c
@@ -4,10 +4,6 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
#include <odp/api/ticketlock.h>
#include <odp/api/shared_memory.h>
#include <odp/api/stash.h>
@@ -17,9 +13,14 @@
#include <odp_debug_internal.h>
#include <odp_global_data.h>
#include <odp_init_internal.h>
+#include <odp_macros_internal.h>
#include <odp_ring_u32_internal.h>
#include <odp_ring_u64_internal.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
ODP_STATIC_ASSERT(CONFIG_INTERNAL_STASHES < CONFIG_MAX_STASHES, "TOO_MANY_INTERNAL_STASHES");
#define MAX_RING_SIZE (1024 * 1024)
@@ -203,7 +204,7 @@ odp_stash_t odp_stash_create(const char *name, const odp_stash_param_t *param)
if (ring_size + 1 <= MIN_RING_SIZE)
ring_size = MIN_RING_SIZE;
else
- ring_size = ROUNDUP_POWER2_U32(ring_size + 1);
+ ring_size = _ODP_ROUNDUP_POWER2_U32(ring_size + 1);
memset(shm_name, 0, sizeof(shm_name));
snprintf(shm_name, sizeof(shm_name) - 1, "_stash_%s", name);
diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c
index 1c54ab740..3af1ae737 100644
--- a/platform/linux-generic/odp_timer.c
+++ b/platform/linux-generic/odp_timer.c
@@ -37,7 +37,6 @@
#include <odp/api/plat/timer_inline_types.h>
-#include <odp_align_internal.h>
#include <odp_atomic_internal.h>
#include <odp_debug_internal.h>
#include <odp_errno_define.h>
@@ -45,6 +44,7 @@
#include <odp_global_data.h>
#include <odp_init_internal.h>
#include <odp_libconfig_internal.h>
+#include <odp_macros_internal.h>
#include <odp_pool_internal.h>
#include <odp_queue_if.h>
#include <odp_timer_internal.h>
@@ -431,9 +431,9 @@ static odp_timer_pool_t timer_pool_new(const char *name,
}
}
- sz0 = ROUNDUP_CACHE_LINE(sizeof(timer_pool_t));
- sz1 = ROUNDUP_CACHE_LINE(sizeof(tick_buf_t) * param->num_timers);
- sz2 = ROUNDUP_CACHE_LINE(sizeof(_odp_timer_t) * param->num_timers);
+ sz0 = _ODP_ROUNDUP_CACHE_LINE(sizeof(timer_pool_t));
+ sz1 = _ODP_ROUNDUP_CACHE_LINE(sizeof(tick_buf_t) * param->num_timers);
+ sz2 = _ODP_ROUNDUP_CACHE_LINE(sizeof(_odp_timer_t) * param->num_timers);
tp_size = sz0 + sz1 + sz2;
shm = odp_shm_reserve(name, tp_size, ODP_CACHE_LINE_SIZE, flags);
diff --git a/platform/linux-generic/odp_timer_wheel.c b/platform/linux-generic/odp_timer_wheel.c
index c50d3a13d..e597d5f70 100644
--- a/platform/linux-generic/odp_timer_wheel.c
+++ b/platform/linux-generic/odp_timer_wheel.c
@@ -632,7 +632,7 @@ static int timer_current_wheel_update(timer_wheels_t *timer_wheels,
slot_idx = wheel_desc->slot_idx;
num_slots = wheel_desc->num_slots;
max_ticks = wheel_desc->max_ticks;
- max_cnt = MIN(elapsed_ticks, UINT32_C(32));
+ max_cnt = _ODP_MIN(elapsed_ticks, UINT32_C(32));
current_wheel = timer_wheels->current_wheel;
ret_code = 0;
rc = -1;
diff --git a/platform/linux-generic/odp_traffic_mngr.c b/platform/linux-generic/odp_traffic_mngr.c
index f02297ec9..9bea659e9 100644
--- a/platform/linux-generic/odp_traffic_mngr.c
+++ b/platform/linux-generic/odp_traffic_mngr.c
@@ -649,7 +649,7 @@ static void tm_shaper_params_cvt_to(const odp_tm_shaper_params_t *shaper_params,
} else {
max_peak_time_delta = tm_max_time_delta(peak_rate);
peak_burst = (int64_t)shaper_params->peak_burst;
- highest_rate = MAX(commit_rate, peak_rate);
+ highest_rate = _ODP_MAX(commit_rate, peak_rate);
min_time_delta = (uint32_t)((1 << 26) / highest_rate);
}
@@ -836,7 +836,7 @@ static void update_shaper_elapsed_time(tm_system_t *tm_system,
else
commit_inc = time_delta * shaper_params->commit_rate;
- shaper_obj->commit_cnt = (int64_t)MIN(max_commit, commit + commit_inc);
+ shaper_obj->commit_cnt = (int64_t)_ODP_MIN(max_commit, commit + commit_inc);
if (shaper_params->dual_rate) {
peak = shaper_obj->peak_cnt;
@@ -846,7 +846,7 @@ static void update_shaper_elapsed_time(tm_system_t *tm_system,
else
peak_inc = time_delta * shaper_params->peak_rate;
- shaper_obj->peak_cnt = (int64_t)MIN(max_peak, peak + peak_inc);
+ shaper_obj->peak_cnt = (int64_t)_ODP_MIN(max_peak, peak + peak_inc);
}
shaper_obj->last_update_time = tm_system->current_time;
@@ -866,9 +866,8 @@ static uint64_t time_till_not_red(tm_shaper_params_t *shaper_params,
commit_delay = (-shaper_obj->commit_cnt)
/ shaper_params->commit_rate;
- min_time_delay =
- MAX(shaper_obj->shaper_params->min_time_delta, UINT64_C(256));
- commit_delay = MAX(commit_delay, min_time_delay);
+ min_time_delay = _ODP_MAX(shaper_obj->shaper_params->min_time_delta, UINT64_C(256));
+ commit_delay = _ODP_MAX(commit_delay, min_time_delay);
if (!shaper_params->dual_rate)
return commit_delay;
@@ -876,13 +875,13 @@ static uint64_t time_till_not_red(tm_shaper_params_t *shaper_params,
if (shaper_obj->peak_cnt < 0)
peak_delay = (-shaper_obj->peak_cnt) / shaper_params->peak_rate;
- peak_delay = MAX(peak_delay, min_time_delay);
+ peak_delay = _ODP_MAX(peak_delay, min_time_delay);
if (0 < shaper_obj->commit_cnt)
return peak_delay;
else if (0 < shaper_obj->peak_cnt)
return commit_delay;
else
- return MIN(commit_delay, peak_delay);
+ return _ODP_MIN(commit_delay, peak_delay);
}
static int delete_timer(tm_system_t *tm_system ODP_UNUSED,
@@ -1192,8 +1191,8 @@ static int tm_set_finish_time(tm_schedulers_obj_t *schedulers_obj,
frame_weight = ((inverted_weight * frame_len) + (1 << 15)) >> 16;
sched_state = &schedulers_obj->sched_states[new_priority];
- base_virtual_time = MAX(prod_shaper_obj->virtual_finish_time,
- sched_state->base_virtual_time);
+ base_virtual_time = _ODP_MAX(prod_shaper_obj->virtual_finish_time,
+ sched_state->base_virtual_time);
virtual_finish_time = base_virtual_time + frame_weight;
prod_shaper_obj->virtual_finish_time = virtual_finish_time;
@@ -1805,7 +1804,7 @@ static odp_tm_percent_t tm_queue_fullness(tm_wred_params_t *wred_params,
return 0;
fullness = (10000 * current_cnt) / max_cnt;
- return (odp_tm_percent_t)MIN(fullness, UINT64_C(50000));
+ return (odp_tm_percent_t)_ODP_MIN(fullness, UINT64_C(50000));
}
static odp_bool_t tm_local_random_drop(tm_system_t *tm_system,
@@ -2228,6 +2227,7 @@ static void tm_egress_marking(tm_system_t *tm_system, odp_packet_t odp_pkt)
tm_tos_marking_t *ip_marking;
color = odp_packet_color(odp_pkt);
+ ODP_ASSERT(color < ODP_NUM_PACKET_COLORS);
if (odp_packet_has_vlan(odp_pkt)) {
vlan_marking = &tm_system->marking.vlan_marking[color];
@@ -2710,11 +2710,10 @@ static void tm_system_capabilities_set(odp_tm_capabilities_t *cap_ptr,
uint32_t min_weight, max_weight;
uint8_t max_priority;
- num_levels = MAX(MIN(req_ptr->num_levels, ODP_TM_MAX_LEVELS), 1);
+ num_levels = _ODP_MAX(_ODP_MIN(req_ptr->num_levels, ODP_TM_MAX_LEVELS), 1);
memset(cap_ptr, 0, sizeof(odp_tm_capabilities_t));
- max_queues = MIN(req_ptr->max_tm_queues,
- (uint32_t)ODP_TM_MAX_NUM_TM_NODES);
+ max_queues = _ODP_MIN(req_ptr->max_tm_queues, (uint32_t)ODP_TM_MAX_NUM_TM_NODES);
shaper_supported = req_ptr->tm_queue_shaper_needed;
wred_supported = req_ptr->tm_queue_wred_needed;
dual_slope = req_ptr->tm_queue_dual_slope_needed;
@@ -2755,16 +2754,16 @@ static void tm_system_capabilities_set(odp_tm_capabilities_t *cap_ptr,
per_level_cap = &cap_ptr->per_level[level_idx];
per_level_req = &req_ptr->per_level[level_idx];
- max_nodes = MIN(per_level_req->max_num_tm_nodes,
- (uint32_t)ODP_TM_MAX_NUM_TM_NODES);
- max_fanin = MIN(per_level_req->max_fanin_per_node,
- UINT32_C(1024));
- max_priority = MIN(per_level_req->max_priority,
- ODP_TM_MAX_PRIORITIES - 1);
- min_weight = MAX(per_level_req->min_weight,
- ODP_TM_MIN_SCHED_WEIGHT);
- max_weight = MIN(per_level_req->max_weight,
- ODP_TM_MAX_SCHED_WEIGHT);
+ max_nodes = _ODP_MIN(per_level_req->max_num_tm_nodes,
+ (uint32_t)ODP_TM_MAX_NUM_TM_NODES);
+ max_fanin = _ODP_MIN(per_level_req->max_fanin_per_node,
+ UINT32_C(1024));
+ max_priority = _ODP_MIN(per_level_req->max_priority,
+ ODP_TM_MAX_PRIORITIES - 1);
+ min_weight = _ODP_MAX(per_level_req->min_weight,
+ ODP_TM_MIN_SCHED_WEIGHT);
+ max_weight = _ODP_MIN(per_level_req->max_weight,
+ ODP_TM_MAX_SCHED_WEIGHT);
shaper_supported = per_level_req->tm_node_shaper_needed;
wred_supported = per_level_req->tm_node_wred_needed;
dual_slope = per_level_req->tm_node_dual_slope_needed;
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c
index 030560b0d..006344b48 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -23,14 +23,15 @@
#include <odp/api/time.h>
#include <odp/api/plat/time_inlines.h>
-#include <odp_align_internal.h>
#include <odp_packet_io_internal.h>
+#include <odp_pool_internal.h>
#include <odp_classification_internal.h>
#include <odp_socket_common.h>
#include <odp_packet_dpdk.h>
#include <odp_debug_internal.h>
#include <odp_libconfig_internal.h>
#include <odp_errno_define.h>
+#include <odp_macros_internal.h>
#include <protocols/eth.h>
#include <protocols/udp.h>
@@ -120,7 +121,7 @@ struct pkt_cache_t {
typedef union ODP_ALIGNED_CACHE {
struct pkt_cache_t s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct pkt_cache_t))];
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(struct pkt_cache_t))];
} pkt_cache_t;
/** Packet IO using DPDK interface */
@@ -153,6 +154,15 @@ typedef struct ODP_ALIGNED_CACHE {
ODP_STATIC_ASSERT(PKTIO_PRIVATE_SIZE >= sizeof(pkt_dpdk_t),
"PKTIO_PRIVATE_SIZE too small");
+typedef struct {
+ uint32_t dpdk_elt_size;
+ uint8_t pool_in_use;
+ struct rte_mempool *pkt_pool;
+} mem_src_data_t;
+
+ODP_STATIC_ASSERT(_ODP_POOL_MEM_SRC_DATA_SIZE >= sizeof(mem_src_data_t),
+ "_ODP_POOL_MEM_SRC_DATA_SIZE too small");
+
static inline struct rte_mbuf *mbuf_from_pkt_hdr(odp_packet_hdr_t *pkt_hdr)
{
return ((struct rte_mbuf *)pkt_hdr) - 1;
@@ -168,6 +178,11 @@ static inline pkt_dpdk_t *pkt_priv(pktio_entry_t *pktio_entry)
return (pkt_dpdk_t *)(uintptr_t)(pktio_entry->s.pkt_priv);
}
+static inline mem_src_data_t *mem_src_priv(uint8_t *data)
+{
+ return (mem_src_data_t *)data;
+}
+
static int disable_pktio; /** !0 this pktio disabled, 0 enabled */
static int dpdk_pktio_init(void);
@@ -320,13 +335,14 @@ static void pktmbuf_init(struct rte_mempool *mp, void *opaque_arg ODP_UNUSED,
* Create custom DPDK packet pool
*/
static struct rte_mempool *mbuf_pool_create(const char *name,
- pool_t *pool_entry)
+ pool_t *pool_entry,
+ uint32_t dpdk_elt_size)
{
odp_shm_info_t shm_info;
struct rte_mempool *mp = NULL;
struct rte_pktmbuf_pool_private mbp_priv;
struct rte_mempool_objsz sz;
- unsigned int elt_size = pool_entry->dpdk_elt_size;
+ unsigned int elt_size = dpdk_elt_size;
unsigned int num = pool_entry->num, populated = 0;
uint32_t total_size;
uint64_t page_size, offset = 0, remainder = 0;
@@ -423,9 +439,10 @@ static int pool_enqueue(struct rte_mempool *mp,
{
odp_packet_t pkt_tbl[num];
pool_t *pool_entry = (pool_t *)mp->pool_config;
+ mem_src_data_t *mem_src_data = mem_src_priv(pool_entry->mem_src_data);
unsigned i;
- if (odp_unlikely(num == 0 || !pool_entry->pool_in_use))
+ if (odp_unlikely(num == 0 || !mem_src_data->pool_in_use))
return 0;
for (i = 0; i < num; i++) {
@@ -497,67 +514,72 @@ static void pool_free(struct rte_mempool *mp)
}
}
-static void pool_destroy(void *pool)
+static void pool_destroy(uint8_t *data)
{
- struct rte_mempool *mp = (struct rte_mempool *)pool;
+ mem_src_data_t *mem_src_data = mem_src_priv(data);
- if (mp != NULL) {
- pool_t *pool_entry = (pool_t *)mp->pool_config;
-
- pool_entry->pool_in_use = 0;
- rte_mempool_free(mp);
+ if (mem_src_data->pkt_pool != NULL) {
+ mem_src_data->pool_in_use = 0;
+ rte_mempool_free(mem_src_data->pkt_pool);
}
+
+ mem_src_data->pkt_pool = NULL;
}
-int _odp_dpdk_pool_create(pool_t *pool)
+static int pool_create(uint8_t *data, pool_t *pool)
{
struct rte_mempool *pkt_pool;
char pool_name[RTE_MEMPOOL_NAMESIZE];
+ mem_src_data_t *mem_src_data = mem_src_priv(data);
+
+ mem_src_data->pkt_pool = NULL;
if (!_ODP_DPDK_ZERO_COPY)
return 0;
- pool->pool_in_use = 0;
-
+ mem_src_data->pool_in_use = 0;
snprintf(pool_name, sizeof(pool_name),
"dpdk_pktpool_%" PRIu32 "_%" PRIu32 "", odp_global_ro.main_pid,
pool->pool_idx);
- pkt_pool = mbuf_pool_create(pool_name, pool);
+ pkt_pool = mbuf_pool_create(pool_name, pool, mem_src_data->dpdk_elt_size);
if (pkt_pool == NULL) {
ODP_ERR("Creating external DPDK pool failed\n");
return -1;
}
- pool->ext_desc = pkt_pool;
- pool->ext_destroy = pool_destroy;
- pool->pool_in_use = 1;
+ mem_src_data->pkt_pool = pkt_pool;
+ mem_src_data->pool_in_use = 1;
return 0;
}
-uint32_t _odp_dpdk_pool_obj_size(pool_t *pool, uint32_t block_size)
+static void pool_obj_size(uint8_t *data, uint32_t *block_size, uint32_t *block_offset,
+ uint32_t *flags)
{
struct rte_mempool_objsz sz;
+ uint32_t size;
uint32_t total_size;
+ mem_src_data_t *mem_src_data = mem_src_priv(data);
if (!_ODP_DPDK_ZERO_COPY)
- return block_size;
+ return;
if (odp_global_rw->dpdk_initialized == 0) {
if (dpdk_pktio_init()) {
ODP_ERR("Initializing DPDK failed\n");
- return 0;
+ *block_size = 0;
+ return;
}
odp_global_rw->dpdk_initialized = 1;
}
- block_size += sizeof(struct rte_mbuf);
- total_size = rte_mempool_calc_obj_size(block_size, MEMPOOL_FLAGS, &sz);
- pool->dpdk_elt_size = sz.elt_size;
- pool->block_offset = sz.header_size + sizeof(struct rte_mbuf);
-
- return total_size;
+ *flags |= ODP_SHM_HP;
+ size = *block_size + sizeof(struct rte_mbuf);
+ total_size = rte_mempool_calc_obj_size(size, MEMPOOL_FLAGS, &sz);
+ mem_src_data->dpdk_elt_size = sz.elt_size;
+ *block_size = total_size;
+ *block_offset = sz.header_size + sizeof(struct rte_mbuf);
}
static struct rte_mempool_ops odp_pool_ops = {
@@ -1735,7 +1757,9 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
pkt_dpdk->min_rx_burst = 0;
if (_ODP_DPDK_ZERO_COPY) {
- pkt_pool = (struct rte_mempool *)pool_entry->ext_desc;
+ mem_src_data_t *mem_src_data = mem_src_priv(pool_entry->mem_src_data);
+
+ pkt_pool = mem_src_data->pkt_pool;
} else {
snprintf(pool_name, sizeof(pool_name), "pktpool_%s", netdev);
/* Check if the pool exists already */
@@ -2406,27 +2430,27 @@ const pktio_if_ops_t _odp_dpdk_pktio_ops = {
.output_queues_config = dpdk_output_queues_config
};
-#else
-
-#include <stdint.h>
-
-#include <odp/api/hints.h>
-
-#include <odp_packet_dpdk.h>
-#include <odp_pool_internal.h>
-
-/*
- * Dummy functions for pool_create()
- */
-
-uint32_t _odp_dpdk_pool_obj_size(pool_t *pool ODP_UNUSED, uint32_t block_size)
+static odp_bool_t is_mem_src_active(void)
{
- return block_size;
+ return !disable_pktio && _ODP_DPDK_ZERO_COPY;
}
-int _odp_dpdk_pool_create(pool_t *pool ODP_UNUSED)
+static void force_mem_src_disable(void)
{
- return 0;
+ if (_ODP_DPDK_ZERO_COPY)
+ disable_pktio = 1;
}
+const _odp_pool_mem_src_ops_t _odp_pool_dpdk_mem_src_ops = {
+ .name = "dpdk_zc",
+ .is_active = is_mem_src_active,
+ .force_disable = force_mem_src_disable,
+ .adjust_size = pool_obj_size,
+ .bind = pool_create,
+ .unbind = pool_destroy
+};
+
+#else
+/* Avoid warning about empty translation unit */
+typedef int _odp_dummy;
#endif /* _ODP_PKTIO_DPDK */
diff --git a/platform/linux-generic/pktio/io_ops.c b/platform/linux-generic/pktio/io_ops.c
index b5a08b58a..f9ea89f71 100644
--- a/platform/linux-generic/pktio/io_ops.c
+++ b/platform/linux-generic/pktio/io_ops.c
@@ -16,6 +16,9 @@ const pktio_if_ops_t * const _odp_pktio_if_ops[] = {
#ifdef _ODP_PKTIO_DPDK
&_odp_dpdk_pktio_ops,
#endif
+#ifdef _ODP_PKTIO_XDP
+ &_odp_sock_xdp_pktio_ops,
+#endif
#ifdef _ODP_PKTIO_NETMAP
&_odp_netmap_pktio_ops,
#endif
diff --git a/platform/linux-generic/pktio/ipc.c b/platform/linux-generic/pktio/ipc.c
index 81938a983..455243159 100644
--- a/platform/linux-generic/pktio/ipc.c
+++ b/platform/linux-generic/pktio/ipc.c
@@ -5,10 +5,12 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <odp/api/system_info.h>
+
#include <odp_debug_internal.h>
#include <odp_packet_io_internal.h>
#include <odp_errno_define.h>
-#include <odp/api/system_info.h>
+#include <odp_macros_internal.h>
#include <odp_shm_internal.h>
#include <odp_ring_ptr_internal.h>
#include <odp_global_data.h>
@@ -124,7 +126,7 @@ static ring_ptr_t *_ring_create(const char *name, uint32_t count,
shm_flags |= ODP_SHM_SINGLE_VA;
/* count must be a power of 2 */
- if (!CHECK_IS_POWER2(count)) {
+ if (!_ODP_CHECK_IS_POWER2(count)) {
ODP_ERR("Requested size is invalid, must be a power of 2\n");
_odp_errno = EINVAL;
return NULL;
@@ -234,17 +236,17 @@ static int _ipc_init_master(pktio_entry_t *pktio_entry,
uint32_t ring_size;
uint32_t ring_mask;
- if ((uint64_t)ROUNDUP_POWER2_U32(pool->num + 1) > UINT32_MAX) {
+ if ((uint64_t)_ODP_ROUNDUP_POWER2_U32(pool->num + 1) > UINT32_MAX) {
ODP_ERR("Too large packet pool\n");
return -1;
}
/* Ring must be able to store all packets in the pool */
- ring_size = ROUNDUP_POWER2_U32(pool->num + 1);
+ ring_size = _ODP_ROUNDUP_POWER2_U32(pool->num + 1);
/* Ring size has to larger than burst size */
if (ring_size <= IPC_BURST_SIZE)
- ring_size = ROUNDUP_POWER2_U32(IPC_BURST_SIZE + 1);
+ ring_size = _ODP_ROUNDUP_POWER2_U32(IPC_BURST_SIZE + 1);
ring_mask = ring_size - 1;
pktio_ipc->ring_size = ring_size;
diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c
index 3e21efecd..c702f9ded 100644
--- a/platform/linux-generic/pktio/loop.c
+++ b/platform/linux-generic/pktio/loop.c
@@ -197,7 +197,7 @@ static int loopback_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
* parser in the case of a segmented packet. */
if (odp_unlikely(seg_len < PARSE_BYTES &&
pkt_len > seg_len)) {
- seg_len = MIN(pkt_len, PARSE_BYTES);
+ seg_len = _ODP_MIN(pkt_len, PARSE_BYTES);
odp_packet_copy_to_mem(pkt, 0, seg_len, buf);
pkt_addr = buf;
} else {
@@ -405,20 +405,9 @@ static int loopback_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
}
for (i = 0; i < nb_tx; ++i) {
- odp_ipsec_packet_result_t result;
-
- if (odp_packet_subtype(pkt_tbl[i]) ==
- ODP_EVENT_PACKET_IPSEC &&
- pktio_entry->s.config.outbound_ipsec) {
-
- /* Possibly postprocessing packet */
- odp_ipsec_result(&result, pkt_tbl[i]);
- }
packet_subtype_set(pkt_tbl[i], ODP_EVENT_PACKET_BASIC);
- }
-
- for (i = 0; i < nb_tx; ++i)
loopback_fix_checksums(pkt_tbl[i], pktout_cfg, pktout_capa);
+ }
odp_ticketlock_lock(&pktio_entry->s.txl);
diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c
index 94b88e21e..342f38431 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -24,17 +24,17 @@
#include <odp_socket_common.h>
#include <odp_debug_internal.h>
#include <odp_errno_define.h>
-#include <protocols/eth.h>
+#include <odp_classification_datamodel.h>
+#include <odp_classification_internal.h>
+#include <odp_libconfig_internal.h>
+#include <odp_macros_internal.h>
+#include <protocols/eth.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <poll.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
-#include <odp_classification_datamodel.h>
-#include <odp_classification_internal.h>
-#include <odp_libconfig_internal.h>
-
#include <inttypes.h>
/* Disable netmap debug prints */
@@ -73,7 +73,7 @@ struct netmap_ring_t {
typedef union ODP_ALIGNED_CACHE {
struct netmap_ring_t s;
- uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct netmap_ring_t))];
+ uint8_t pad[_ODP_ROUNDUP_CACHE_LINE(sizeof(struct netmap_ring_t))];
} netmap_ring_t;
/** Netmap ring slot */
diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c
index 9d1bbe545..0d756c4e1 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -289,7 +289,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
/* Make sure there is enough data for the packet
* parser in the case of a segmented packet. */
if (odp_unlikely(seg_len < PARSE_BYTES && pkt_len > seg_len)) {
- seg_len = MIN(pkt_len, PARSE_BYTES);
+ seg_len = _ODP_MIN(pkt_len, PARSE_BYTES);
odp_packet_copy_to_mem(pkt, 0, seg_len, buf);
base = buf;
}
diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c
index 7824b0e91..4845b5dab 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -25,6 +25,7 @@
#include <odp_classification_datamodel.h>
#include <odp_classification_internal.h>
#include <odp_global_data.h>
+#include <odp_macros_internal.h>
#include <protocols/eth.h>
#include <protocols/ip.h>
@@ -433,8 +434,7 @@ static int mmap_setup_ring(pkt_sock_mmap_t *pkt_sock, struct ring *ring,
ring->type = type;
ring->version = TPACKET_V2;
- frame_size = ROUNDUP_POWER2_U32(mtu + TPACKET_HDRLEN
- + TPACKET_ALIGNMENT);
+ frame_size = _ODP_ROUNDUP_POWER2_U32(mtu + TPACKET_HDRLEN + TPACKET_ALIGNMENT);
block_size = BLOCK_SIZE;
if (frame_size > block_size)
block_size = frame_size;
diff --git a/platform/linux-generic/pktio/socket_xdp.c b/platform/linux-generic/pktio/socket_xdp.c
new file mode 100644
index 000000000..e43e4bf89
--- /dev/null
+++ b/platform/linux-generic/pktio/socket_xdp.c
@@ -0,0 +1,688 @@
+/* Copyright (c) 2022, Nokia
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/autoheader_internal.h>
+
+#ifdef _ODP_PKTIO_XDP
+
+#include <odp_posix_extensions.h>
+#include <odp/api/debug.h>
+#include <odp/api/hints.h>
+#include <odp/api/system_info.h>
+#include <odp/api/ticketlock.h>
+
+#include <odp_debug_internal.h>
+#include <odp_macros_internal.h>
+#include <odp_packet_io_internal.h>
+#include <odp_packet_internal.h>
+#include <odp_parse_internal.h>
+#include <odp_classification_internal.h>
+#include <odp_socket_common.h>
+
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <xdp/xsk.h>
+
+#define NUM_XDP_DESCS 1024U
+#define MIN_FRAME_SIZE 2048U
+#define IF_DELIM " "
+#define Q_DELIM ':'
+
+typedef struct {
+ struct xsk_ring_prod fill_q;
+ struct xsk_ring_cons compl_q;
+ struct xsk_umem *umem;
+ pool_t *pool;
+} xdp_umem_info_t;
+
+typedef struct {
+ struct xsk_ring_cons rx;
+ struct xsk_ring_cons compl_q;
+ struct xsk_ring_prod tx;
+ struct xsk_ring_prod fill_q;
+ xdp_umem_info_t *umem_info;
+ struct xsk_socket *xsk;
+ int pktio_idx;
+ int helper_sock;
+ uint32_t mtu;
+ uint32_t max_mtu;
+} xdp_sock_info_t;
+
+typedef struct {
+ odp_ticketlock_t rx_lock ODP_ALIGNED_CACHE;
+ odp_ticketlock_t tx_lock ODP_ALIGNED_CACHE;
+ xdp_sock_info_t sock_info;
+} pkt_xdp_t;
+
+typedef struct {
+ odp_packet_hdr_t *pkt_hdr;
+ odp_packet_t pkt;
+ uint8_t *data;
+ uint32_t len;
+} pkt_data_t;
+
+ODP_STATIC_ASSERT(PKTIO_PRIVATE_SIZE >= sizeof(pkt_xdp_t),
+ "PKTIO_PRIVATE_SIZE too small");
+
+static odp_bool_t disable_pktio;
+
+static int sock_xdp_init_global(void)
+{
+ if (getenv("ODP_PKTIO_DISABLE_SOCKET_XDP")) {
+ ODP_PRINT("PKTIO: socket xdp skipped,"
+ " enabled export ODP_PKTIO_DISABLE_SOCKET_XDP=1.\n");
+ disable_pktio = true;
+ } else {
+ ODP_PRINT("PKTIO: initialized socket xdp,"
+ " use export ODP_PKTIO_DISABLE_SOCKET_XDP=1 to disable.\n");
+ }
+
+ return 0;
+}
+
+static inline pkt_xdp_t *pkt_priv(pktio_entry_t *pktio_entry)
+{
+ return (pkt_xdp_t *)(uintptr_t)(pktio_entry->s.pkt_priv);
+}
+
+static void fill_socket_config(struct xsk_socket_config *config)
+{
+ config->rx_size = NUM_XDP_DESCS;
+ config->tx_size = NUM_XDP_DESCS;
+ config->libxdp_flags = 0U;
+ config->xdp_flags = 0U;
+ config->bind_flags = XDP_ZEROCOPY; /* TODO: XDP_COPY */
+}
+
+static uint32_t get_bind_queue_index(const char *devname)
+{
+ const char *param = getenv("ODP_PKTIO_XDP_PARAMS");
+ char *tmp_str;
+ char *tmp;
+ char *if_str;
+ int idx = 0;
+
+ if (param == NULL)
+ goto out;
+
+ tmp_str = strdup(param);
+
+ if (tmp_str == NULL)
+ goto out;
+
+ tmp = strtok(tmp_str, IF_DELIM);
+
+ if (tmp == NULL)
+ goto out_str;
+
+ while (tmp) {
+ if_str = strchr(tmp, Q_DELIM);
+
+ if (if_str != NULL && if_str != &tmp[strlen(tmp) - 1U]) {
+ if (strncmp(devname, tmp, (uint64_t)(uintptr_t)(if_str - tmp)) == 0) {
+ idx = _ODP_MAX(atoi(++if_str), 0);
+ break;
+ }
+ }
+
+ tmp = strtok(NULL, IF_DELIM);
+ }
+
+out_str:
+ free(tmp_str);
+
+out:
+ return idx;
+}
+
+static odp_bool_t reserve_fill_queue_elements(xdp_sock_info_t *sock_info, int num)
+{
+ pool_t *pool;
+ odp_packet_t packets[num];
+ int count;
+ struct xsk_ring_prod *fill_q;
+ uint32_t start_idx;
+ int pktio_idx;
+ uint32_t block_size;
+ odp_packet_hdr_t *pkt_hdr;
+
+ pool = sock_info->umem_info->pool;
+ count = odp_packet_alloc_multi(pool->pool_hdl, sock_info->mtu, packets, num);
+
+ if (count <= 0)
+ return false;
+
+ fill_q = &sock_info->fill_q;
+
+ if (xsk_ring_prod__reserve(fill_q, count, &start_idx) == 0U) {
+ odp_packet_free_multi(packets, count);
+ return false;
+ }
+
+ pktio_idx = sock_info->pktio_idx;
+ block_size = pool->block_size;
+
+ for (int i = 0; i < count; ++i) {
+ pkt_hdr = packet_hdr(packets[i]);
+ pkt_hdr->ms_pktio_idx = pktio_idx;
+ *xsk_ring_prod__fill_addr(fill_q, start_idx++) =
+ pkt_hdr->event_hdr.index.event * block_size;
+ }
+
+ xsk_ring_prod__submit(&sock_info->fill_q, count);
+
+ return true;
+}
+
+static int sock_xdp_open(odp_pktio_t pktio, pktio_entry_t *pktio_entry, const char *devname,
+ odp_pool_t pool_hdl)
+{
+ pkt_xdp_t *priv;
+ pool_t *pool;
+ struct xsk_socket_config config;
+ uint32_t bind_q;
+ int ret;
+
+ if (disable_pktio)
+ return -1;
+
+ priv = pkt_priv(pktio_entry);
+ memset(priv, 0, sizeof(pkt_xdp_t));
+ pool = pool_entry_from_hdl(pool_hdl);
+ priv->sock_info.umem_info = (xdp_umem_info_t *)pool->mem_src_data;
+ priv->sock_info.xsk = NULL;
+ /* Mark transitory kernel-owned packets with the pktio index, so that they can be freed on
+ * close. */
+ priv->sock_info.pktio_idx = 1 + odp_pktio_index(pktio);
+ fill_socket_config(&config);
+ bind_q = get_bind_queue_index(devname);
+ /* With xsk_socket__create_shared(), as only one bind queue index can
+ * be passed, NIC in use needs to be configured accordingly to have
+ * only a single combined TX-RX queue, otherwise traffic may not end up
+ * on the socket. For now, always bind to the first queue (overridable
+ * with environment variable). */
+ ret = xsk_socket__create_shared(&priv->sock_info.xsk, devname, bind_q,
+ priv->sock_info.umem_info->umem, &priv->sock_info.rx,
+ &priv->sock_info.tx, &priv->sock_info.fill_q,
+ &priv->sock_info.compl_q, &config);
+
+ if (ret) {
+ ODP_ERR("Error creating xdp socket for bind queue %u: %d\n", bind_q, ret);
+ goto xsk_err;
+ }
+
+ /* Ring setup/clean up routines seem to be asynchronous with some drivers and might not be
+ * ready yet after xsk_socket__create_shared(). */
+ sleep(1U);
+
+ /* Querying with ioctl() via AF_XDP socket doesn't seem to work, so
+ * create a helper socket for this. */
+ priv->sock_info.helper_sock = -1;
+ ret = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (ret == -1) {
+ ODP_ERR("Error creating helper socket for xdp: %s\n", strerror(errno));
+ goto sock_err;
+ }
+
+ priv->sock_info.helper_sock = ret;
+ priv->sock_info.mtu = _odp_mtu_get_fd(priv->sock_info.helper_sock, devname);
+
+ if (priv->sock_info.mtu == 0U)
+ goto res_err;
+
+ priv->sock_info.max_mtu = pool->seg_len;
+
+ if (!reserve_fill_queue_elements(&priv->sock_info, config.rx_size)) {
+ ODP_ERR("Unable to reserve fill queue descriptors.\n");
+ goto res_err;
+ }
+
+ odp_ticketlock_init(&priv->rx_lock);
+ odp_ticketlock_init(&priv->tx_lock);
+
+ return 0;
+
+res_err:
+ close(priv->sock_info.helper_sock);
+ priv->sock_info.helper_sock = -1;
+
+sock_err:
+ xsk_socket__delete(priv->sock_info.xsk);
+ priv->sock_info.xsk = NULL;
+
+xsk_err:
+ return -1;
+}
+
+static int sock_xdp_close(pktio_entry_t *pktio_entry)
+{
+ pkt_xdp_t *priv = pkt_priv(pktio_entry);
+ pool_t *pool = priv->sock_info.umem_info->pool;
+ odp_packet_hdr_t *pkt_hdr;
+
+ if (priv->sock_info.helper_sock != -1)
+ close(priv->sock_info.helper_sock);
+
+ if (priv->sock_info.xsk != NULL)
+ xsk_socket__delete(priv->sock_info.xsk);
+
+ /* Ring setup/clean up routines seem to be asynchronous with some drivers and might not be
+ * ready yet after xsk_socket__delete(). */
+ sleep(1U);
+
+ /* Free all packets that were in fill or completion queues at the time of closing. */
+ for (uint32_t i = 0U; i < pool->num + pool->skipped_blocks; ++i) {
+ pkt_hdr = packet_hdr(packet_from_event_hdr(event_hdr_from_index(pool, i)));
+
+ if (pkt_hdr->ms_pktio_idx == priv->sock_info.pktio_idx) {
+ pkt_hdr->ms_pktio_idx = 0U;
+ odp_packet_free(packet_handle(pkt_hdr));
+ }
+ }
+
+ return 0;
+}
+
+static inline void extract_data(const struct xdp_desc *rx_desc, uint8_t *pool_base_addr,
+ pkt_data_t *pkt_data)
+{
+ uint64_t frame_off;
+ uint64_t pkt_off;
+
+ /* UMEM "addresses" are offsets from start of a registered UMEM area.
+ * Additionally, the packet data offset (where received packet data
+ * starts within a UMEM frame) is encoded to the UMEM address with
+ * XSK_UNALIGNED_BUF_OFFSET_SHIFT left bitshift when XDP_ZEROCOPY and
+ * XDP_UMEM_UNALIGNED_CHUNK_FLAG are enabled. */
+ frame_off = rx_desc->addr;
+ pkt_off = xsk_umem__add_offset_to_addr(frame_off);
+ frame_off = xsk_umem__extract_addr(frame_off);
+ pkt_data->pkt_hdr = xsk_umem__get_data(pool_base_addr, frame_off);
+ pkt_data->pkt = packet_handle(pkt_data->pkt_hdr);
+ pkt_data->data = xsk_umem__get_data(pool_base_addr, pkt_off);
+ pkt_data->len = rx_desc->len;
+}
+
+static uint32_t process_received(pktio_entry_t *pktio_entry, xdp_sock_info_t *sock_info,
+ uint32_t start_idx, odp_packet_t packets[], int num)
+{
+ pkt_data_t pkt_data;
+ struct xsk_ring_cons *rx = &sock_info->rx;
+ uint8_t *base_addr = sock_info->umem_info->pool->base_addr;
+ const odp_proto_layer_t layer = pktio_entry->s.parse_layer;
+ const odp_proto_chksums_t in_chksums = pktio_entry->s.in_chksums;
+ const odp_pktin_config_opt_t opt = pktio_entry->s.config.pktin;
+ uint64_t l4_part_sum = 0U;
+ odp_pool_t *pool_hdl = &sock_info->umem_info->pool->pool_hdl;
+ odp_pktio_t pktio_hdl = pktio_entry->s.handle;
+ uint32_t num_rx = 0U;
+
+ for (int i = 0; i < num; ++i) {
+ extract_data(xsk_ring_cons__rx_desc(rx, start_idx++), base_addr, &pkt_data);
+ pkt_data.pkt_hdr->ms_pktio_idx = 0U;
+ packet_init(pkt_data.pkt_hdr, pkt_data.len);
+
+ if (layer) {
+ if (_odp_packet_parse_common(&pkt_data.pkt_hdr->p, pkt_data.data,
+ pkt_data.len, pkt_data.len,
+ layer, in_chksums, &l4_part_sum, opt) < 0) {
+ odp_packet_free(pkt_data.pkt);
+ continue;
+ }
+
+ if (pktio_cls_enabled(pktio_entry) &&
+ _odp_cls_classify_packet(pktio_entry, pkt_data.data, pool_hdl,
+ pkt_data.pkt_hdr)) {
+ odp_packet_free(pkt_data.pkt);
+ continue;
+ }
+ }
+
+ pkt_data.pkt_hdr->seg_data = pkt_data.data;
+ pkt_data.pkt_hdr->event_hdr.base_data = pkt_data.data;
+ pkt_data.pkt_hdr->input = pktio_hdl;
+ packets[num_rx++] = pkt_data.pkt;
+ }
+
+ return num_rx;
+}
+
+static int sock_xdp_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_packet_t packets[],
+ int num)
+{
+ pkt_xdp_t *priv;
+ struct pollfd fd;
+ uint32_t start_idx = 0U, recvd, procd;
+
+ priv = pkt_priv(pktio_entry);
+ odp_ticketlock_lock(&priv->rx_lock);
+
+ if (odp_unlikely(xsk_ring_prod__needs_wakeup(&priv->sock_info.fill_q))) {
+ fd.fd = xsk_socket__fd(priv->sock_info.xsk);
+ fd.events = POLLIN;
+ (void)poll(&fd, 1U, 0);
+ }
+
+ recvd = xsk_ring_cons__peek(&priv->sock_info.rx, num, &start_idx);
+
+ if (recvd == 0U) {
+ odp_ticketlock_unlock(&priv->rx_lock);
+ return 0;
+ }
+
+ procd = process_received(pktio_entry, &priv->sock_info, start_idx, packets, recvd);
+ xsk_ring_cons__release(&priv->sock_info.rx, recvd);
+ (void)reserve_fill_queue_elements(&priv->sock_info, recvd);
+ odp_ticketlock_unlock(&priv->rx_lock);
+
+ return procd;
+}
+
+static inline void populate_tx_desc(pool_t *pool, odp_packet_hdr_t *pkt_hdr,
+ struct xdp_desc *tx_desc)
+{
+ uint64_t frame_off;
+ uint64_t pkt_off;
+
+ frame_off = pkt_hdr->event_hdr.index.event * pool->block_size;
+ pkt_off = (uint64_t)(uintptr_t)pkt_hdr->event_hdr.base_data
+ - (uint64_t)(uintptr_t)pool->base_addr - frame_off;
+ pkt_off <<= XSK_UNALIGNED_BUF_OFFSET_SHIFT;
+ tx_desc->addr = frame_off | pkt_off;
+ tx_desc->len = pkt_hdr->frame_len;
+}
+
+static void handle_pending_tx(xdp_sock_info_t *sock_info, int num)
+{
+ struct xsk_ring_cons *compl_q;
+ uint32_t sent;
+ uint8_t *base_addr;
+ uint32_t start_idx;
+ uint64_t frame_off;
+ odp_packet_t pkt;
+
+ if (odp_unlikely(xsk_ring_prod__needs_wakeup(&sock_info->tx)))
+ (void)sendto(xsk_socket__fd(sock_info->xsk), NULL, 0U, MSG_DONTWAIT, NULL, 0U);
+
+ compl_q = &sock_info->compl_q;
+ sent = xsk_ring_cons__peek(compl_q, num, &start_idx);
+ base_addr = sock_info->umem_info->pool->base_addr;
+
+ odp_packet_t packets[sent];
+
+ if (sent) {
+ for (uint32_t i = 0U; i < sent; ++i) {
+ frame_off = *xsk_ring_cons__comp_addr(compl_q, start_idx++);
+ frame_off = xsk_umem__extract_addr(frame_off);
+ pkt = xsk_umem__get_data(base_addr, frame_off);
+ packets[i] = pkt;
+ packet_hdr(packets[i])->ms_pktio_idx = 0U;
+ }
+
+ odp_packet_free_multi(packets, sent);
+ xsk_ring_cons__release(compl_q, sent);
+ }
+}
+
+static int sock_xdp_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
+ const odp_packet_t packets[], int num)
+{
+ pkt_xdp_t *priv;
+ xdp_sock_info_t *sock_info;
+ pool_t *pool;
+ odp_pool_t pool_hdl;
+ int pktio_idx, i;
+ struct xsk_ring_prod *tx;
+ odp_packet_t pkt;
+ odp_packet_hdr_t *pkt_hdr;
+ uint32_t start_idx;
+
+ if (odp_unlikely(num == 0))
+ return 0;
+
+ priv = pkt_priv(pktio_entry);
+ odp_ticketlock_lock(&priv->tx_lock);
+ sock_info = &priv->sock_info;
+ pool = sock_info->umem_info->pool;
+ pool_hdl = pool->pool_hdl;
+ pktio_idx = sock_info->pktio_idx;
+ tx = &sock_info->tx;
+
+ for (i = 0; i < num; ++i) {
+ pkt = ODP_PACKET_INVALID;
+
+ if (odp_unlikely(odp_packet_num_segs(packets[i])) > 1) {
+ /* TODO: handle segmented packets */
+ ODP_ERR("Only single-segment packets supported\n");
+ break;
+ }
+
+ pkt_hdr = packet_hdr(packets[i]);
+
+ if (pkt_hdr->event_hdr.pool_ptr != pool) {
+ pkt = odp_packet_copy(packets[i], pool_hdl);
+
+ if (odp_unlikely(pkt == ODP_PACKET_INVALID))
+ break;
+
+ pkt_hdr = packet_hdr(pkt);
+ }
+
+ if (xsk_ring_prod__reserve(tx, 1U, &start_idx) == 0U) {
+ handle_pending_tx(sock_info, NUM_XDP_DESCS);
+
+ if (xsk_ring_prod__reserve(tx, 1U, &start_idx) == 0U) {
+ if (pkt != ODP_PACKET_INVALID)
+ odp_packet_free(pkt);
+
+ break;
+ }
+ }
+
+ if (pkt != ODP_PACKET_INVALID)
+ odp_packet_free(packets[i]);
+
+ pkt_hdr->ms_pktio_idx = pktio_idx;
+ populate_tx_desc(pool, pkt_hdr, xsk_ring_prod__tx_desc(tx, start_idx));
+ }
+
+ xsk_ring_prod__submit(tx, i);
+ handle_pending_tx(sock_info, NUM_XDP_DESCS);
+ odp_ticketlock_unlock(&priv->tx_lock);
+
+ return i;
+}
+
+static uint32_t sock_xdp_mtu_get(pktio_entry_t *pktio_entry)
+{
+ return pkt_priv(pktio_entry)->sock_info.mtu;
+}
+
+static int sock_xdp_mtu_set(pktio_entry_t *pktio_entry, uint32_t maxlen_input,
+ uint32_t maxlen_output ODP_UNUSED)
+{
+ pkt_xdp_t *priv = pkt_priv(pktio_entry);
+ int ret;
+
+ ret = _odp_mtu_set_fd(priv->sock_info.helper_sock, pktio_entry->s.name, maxlen_input);
+ if (ret)
+ return ret;
+
+ priv->sock_info.mtu = maxlen_input;
+
+ return 0;
+}
+
+static int sock_xdp_promisc_mode_set(pktio_entry_t *pktio_entry, int enable)
+{
+ return _odp_promisc_mode_set_fd(pkt_priv(pktio_entry)->sock_info.helper_sock,
+ pktio_entry->s.name, enable);
+}
+
+static int sock_xdp_promisc_mode_get(pktio_entry_t *pktio_entry)
+{
+ return _odp_promisc_mode_get_fd(pkt_priv(pktio_entry)->sock_info.helper_sock,
+ pktio_entry->s.name);
+}
+
+static int sock_xdp_mac_addr_get(pktio_entry_t *pktio_entry ODP_UNUSED, void *mac_addr)
+{
+ return _odp_mac_addr_get_fd(pkt_priv(pktio_entry)->sock_info.helper_sock,
+ pktio_entry->s.name, mac_addr) ? -1 : ETH_ALEN;
+}
+
+static int sock_xdp_link_status(pktio_entry_t *pktio_entry)
+{
+ return _odp_link_status_fd(pkt_priv(pktio_entry)->sock_info.helper_sock,
+ pktio_entry->s.name);
+}
+
+static int sock_xdp_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info)
+{
+ return _odp_link_info_fd(pkt_priv(pktio_entry)->sock_info.helper_sock,
+ pktio_entry->s.name, info);
+}
+
+static int sock_xdp_capability(pktio_entry_t *pktio_entry, odp_pktio_capability_t *capa)
+{
+ pkt_xdp_t *priv = pkt_priv(pktio_entry);
+
+ memset(capa, 0, sizeof(odp_pktio_capability_t));
+ capa->max_input_queues = 1U;
+ capa->max_output_queues = 1U;
+ capa->set_op.op.promisc_mode = 1U;
+ capa->set_op.op.maxlen = 1U;
+
+ capa->maxlen.equal = true;
+ capa->maxlen.min_input = _ODP_SOCKET_MTU_MIN;
+ capa->maxlen.max_input = priv->sock_info.max_mtu;
+ capa->maxlen.min_output = _ODP_SOCKET_MTU_MIN;
+ capa->maxlen.max_output = priv->sock_info.max_mtu;
+
+ capa->config.parser.layer = ODP_PROTO_LAYER_ALL;
+
+ capa->stats.pktio.all_counters = 0U;
+ capa->stats.pktin_queue.all_counters = 0U;
+ capa->stats.pktout_queue.all_counters = 0U;
+
+ return 0;
+}
+
+const pktio_if_ops_t _odp_sock_xdp_pktio_ops = {
+ /* TODO: at least stats */
+ .name = "socket_xdp",
+ .print = NULL,
+ .init_global = sock_xdp_init_global,
+ .init_local = NULL,
+ .term = NULL,
+ .open = sock_xdp_open,
+ .close = sock_xdp_close,
+ .start = NULL,
+ .stop = NULL,
+ .stats = NULL,
+ .stats_reset = NULL,
+ .pktin_queue_stats = NULL,
+ .pktout_queue_stats = NULL,
+ .extra_stat_info = NULL,
+ .extra_stats = NULL,
+ .extra_stat_counter = NULL,
+ .pktio_ts_res = NULL,
+ .pktio_ts_from_ns = NULL,
+ .pktio_time = NULL,
+ .recv = sock_xdp_recv,
+ .recv_tmo = NULL,
+ .recv_mq_tmo = NULL,
+ .fd_set = NULL,
+ .send = sock_xdp_send,
+ .maxlen_get = sock_xdp_mtu_get,
+ .maxlen_set = sock_xdp_mtu_set,
+ .promisc_mode_set = sock_xdp_promisc_mode_set,
+ .promisc_mode_get = sock_xdp_promisc_mode_get,
+ .mac_get = sock_xdp_mac_addr_get,
+ .mac_set = NULL,
+ .link_status = sock_xdp_link_status,
+ .link_info = sock_xdp_link_info,
+ .capability = sock_xdp_capability,
+ .config = NULL,
+ .input_queues_config = NULL,
+ .output_queues_config = NULL
+};
+
+static odp_bool_t sock_xdp_is_mem_src_active(void)
+{
+ return !disable_pktio;
+}
+
+static void sock_xdp_force_mem_src_disable(void)
+{
+ disable_pktio = true;
+}
+
+static void sock_xdp_adjust_block_size(uint8_t *data ODP_UNUSED, uint32_t *block_size,
+ uint32_t *block_offset ODP_UNUSED, uint32_t *flags)
+{
+ const uint32_t size = *block_size + XDP_PACKET_HEADROOM;
+ const uint64_t ps = odp_sys_page_size();
+ /* AF_XDP requires frames to be between 2kB and page size, so with
+ * XDP_ZEROCOPY, if block size is less than 2kB, adjust it to 2kB, if
+ * it is larger than page size, make pool creation fail. */
+ if (disable_pktio)
+ return;
+
+ if (size > ps) {
+ ODP_ERR("Adjusted pool block size larger than page size: %u > %" PRIu64 "\n",
+ size, ps);
+ *block_size = 0U;
+ }
+
+ *flags |= ODP_SHM_HP;
+ *block_size = _ODP_MAX(size, MIN_FRAME_SIZE);
+}
+
+static int sock_xdp_umem_create(uint8_t *data, pool_t *pool)
+{
+ struct xsk_umem_config cfg;
+ xdp_umem_info_t *umem_info = (xdp_umem_info_t *)data;
+
+ umem_info->pool = pool;
+ /* Fill queue size is recommended to be >= HW RX ring size + AF_XDP RX
+ * ring size, so use size twice the size of AF_XDP RX ring. */
+ cfg.fill_size = NUM_XDP_DESCS * 2U; /* TODO: num descs vs pool size */
+ cfg.comp_size = NUM_XDP_DESCS;
+ cfg.frame_size = pool->block_size;
+ cfg.frame_headroom = sizeof(odp_packet_hdr_t) + pool->headroom;
+ cfg.flags = XDP_UMEM_UNALIGNED_CHUNK_FLAG;
+
+ return xsk_umem__create(&umem_info->umem, pool->base_addr, pool->shm_size,
+ &umem_info->fill_q, &umem_info->compl_q, &cfg);
+}
+
+static void sock_xdp_umem_delete(uint8_t *data)
+{
+ xdp_umem_info_t *umem_info = (xdp_umem_info_t *)data;
+
+ while (xsk_umem__delete(umem_info->umem) == -EBUSY)
+ continue;
+}
+
+const _odp_pool_mem_src_ops_t _odp_pool_sock_xdp_mem_src_ops = {
+ .name = "xdp_zc",
+ .is_active = sock_xdp_is_mem_src_active,
+ .force_disable = sock_xdp_force_mem_src_disable,
+ .adjust_size = sock_xdp_adjust_block_size,
+ .bind = sock_xdp_umem_create,
+ .unbind = sock_xdp_umem_delete
+};
+
+#else
+/* Avoid warning about empty translation unit */
+typedef int _odp_dummy;
+#endif