diff options
Diffstat (limited to 'platform/linux-generic')
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 |