diff options
Diffstat (limited to 'platform')
64 files changed, 2582 insertions, 1975 deletions
diff --git a/platform/Makefile.inc b/platform/Makefile.inc index e40a14f04..25c89e91c 100644 --- a/platform/Makefile.inc +++ b/platform/Makefile.inc @@ -57,8 +57,9 @@ odpapispecinclude_HEADERS = \ $(top_srcdir)/include/odp/api/spec/ticketlock.h \ $(top_srcdir)/include/odp/api/spec/time.h \ $(top_srcdir)/include/odp/api/spec/timer.h \ - $(top_builddir)/include/odp/api/spec/version.h \ - $(top_srcdir)/include/odp/api/spec/traffic_mngr.h + $(top_srcdir)/include/odp/api/spec/traffic_mngr.h \ + $(top_builddir)/include/odp/api/spec/deprecated.h \ + $(top_builddir)/include/odp/api/spec/version.h odpapiabidefaultincludedir= $(includedir)/odp/arch/default/api/abi odpapiabidefaultinclude_HEADERS = \ @@ -97,4 +98,6 @@ EXTRA_DIST = \ arch/powerpc/odp_sysinfo_parse.c \ arch/x86/odp/api/cpu_arch.h \ arch/x86/odp_cpu_arch.c \ - arch/x86/odp_sysinfo_parse.c + arch/x86/odp_sysinfo_parse.c \ + arch/x86/cpu_flags.c \ + arch/x86/cpu_flags.h diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am index dfbc57619..c1497f0f6 100644 --- a/platform/linux-dpdk/Makefile.am +++ b/platform/linux-dpdk/Makefile.am @@ -42,6 +42,7 @@ odpapiinclude_HEADERS = \ $(srcdir)/include/odp/api/cpumask.h \ $(srcdir)/include/odp/api/crypto.h \ $(srcdir)/include/odp/api/debug.h \ + $(srcdir)/include/odp/api/deprecated.h \ $(srcdir)/include/odp/api/errno.h \ $(srcdir)/include/odp/api/event.h \ $(srcdir)/include/odp/api/hash.h \ @@ -154,7 +155,7 @@ noinst_HEADERS = \ ${top_srcdir}/platform/linux-generic/include/odp_schedule_if.h \ ${top_srcdir}/platform/linux-generic/include/odp_sorted_list_internal.h \ ${top_srcdir}/platform/linux-generic/include/odp_shm_internal.h \ - ${srcdir}/include/odp_time_internal.h \ + ${top_srcdir}/platform/linux-generic/include/odp_time_internal.h \ ${top_srcdir}/platform/linux-generic/include/odp_timer_internal.h \ ${top_srcdir}/platform/linux-generic/include/odp_timer_wheel_internal.h \ ${top_srcdir}/platform/linux-generic/include/odp_traffic_mngr_internal.h \ @@ -217,12 +218,18 @@ __LIB__libodp_dpdk_la_SOURCES = \ arch/@ARCH_DIR@/odp_cpu_arch.c \ arch/@ARCH_DIR@/odp_sysinfo_parse.c +__LIB__libodp_dpdk_la_LIBADD = $(ATOMIC_LIBS) + +if ARCH_IS_X86 +__LIB__libodp_dpdk_la_SOURCES += arch/@ARCH_DIR@/cpu_flags.c +endif + # Create symlink for ABI header files. Application does not need to use the arch # specific include path for installed files. install-data-hook: - if [ -h $(prefix)/include/odp/api/abi ]; then \ - : \ + if [ -h $(DESTDIR)$(prefix)/include/odp/api/abi ]; then \ + : ; \ else \ - $(LN_S) -rf $(prefix)/include/odp/arch/@ARCH_ABI@/odp/api/abi \ - $(prefix)/include/odp/api/abi; \ + $(LN_S) -rf $(DESTDIR)$(prefix)/include/odp/arch/@ARCH_ABI@/odp/api/abi \ + $(DESTDIR)$(prefix)/include/odp/api/abi; \ fi diff --git a/platform/linux-dpdk/include/odp/api/deprecated.h b/platform/linux-dpdk/include/odp/api/deprecated.h new file mode 120000 index 000000000..42bc7ef16 --- /dev/null +++ b/platform/linux-dpdk/include/odp/api/deprecated.h @@ -0,0 +1 @@ +../../../../linux-generic/include/odp/api/deprecated.h
\ No newline at end of file diff --git a/platform/linux-dpdk/include/odp/api/plat/packet_types.h b/platform/linux-dpdk/include/odp/api/plat/packet_types.h index c6ee3966f..5df0a41ec 100644 --- a/platform/linux-dpdk/include/odp/api/plat/packet_types.h +++ b/platform/linux-dpdk/include/odp/api/plat/packet_types.h @@ -99,8 +99,8 @@ typedef union { /** All input flags */ uint64_t all; + /** Individual input flags */ struct { - uint64_t parsed_l2:1; /**< L2 parsed */ uint64_t dst_queue:1; /**< Dst queue present */ uint64_t timestamp:1; /**< Timestamp present */ diff --git a/platform/linux-dpdk/include/odp/api/plat/time_types.h b/platform/linux-dpdk/include/odp/api/plat/time_types.h index e53ad2f97..b42bc83c2 100644..120000 --- a/platform/linux-dpdk/include/odp/api/plat/time_types.h +++ b/platform/linux-dpdk/include/odp/api/plat/time_types.h @@ -1,43 +1 @@ -/* Copyright (c) 2016, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/** - * @file - * - * ODP time service - */ - -#ifndef ODP_TIME_TYPES_H_ -#define ODP_TIME_TYPES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** @addtogroup odp_time - * @{ - **/ - -/** - * @internal Time structure used to isolate odp-linux implementation from - * the linux timespec structure, which is dependent on POSIX extension level. - */ -typedef struct odp_time_t { - int64_t tv_sec; /**< @internal Seconds or DPDK ticks */ - int64_t tv_nsec; /**< @internal Nanoseconds */ -} odp_time_t; - -#define ODP_TIME_NULL ((odp_time_t){0, 0}) - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif +../../../../../linux-generic/include/odp/api/plat/time_types.h
\ No newline at end of file diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h index d3f00847e..481e4afb1 100644 --- a/platform/linux-dpdk/include/odp_packet_internal.h +++ b/platform/linux-dpdk/include/odp_packet_internal.h @@ -84,18 +84,6 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), "OUTPUT_FLAGS_SIZE_ERROR"); /** - * Protocol stack layers - */ -typedef enum { - LAYER_NONE = 0, - LAYER_L1, - LAYER_L2, - LAYER_L3, - LAYER_L4, - LAYER_ALL -} layer_t; - -/** * Packet parser metadata */ typedef struct { @@ -106,14 +94,6 @@ typedef struct { uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */ uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */ uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also ICMP) */ - - uint32_t l3_len; /**< Layer 3 length */ - uint32_t l4_len; /**< Layer 4 length */ - - uint16_t ethtype; /**< EtherType */ - uint8_t ip_proto; /**< IP protocol */ - uint8_t parsed_layers; /**< Highest parsed protocol stack layer */ - } packet_parser_t; /** @@ -190,58 +170,25 @@ static inline void packet_set_len(odp_packet_hdr_t *pkt_hdr, uint32_t len) rte_pktmbuf_pkt_len(&pkt_hdr->buf_hdr.mb) = len; } -static inline int packet_parse_l2_not_done(packet_parser_t *prs) -{ - return !prs->input_flags.parsed_l2; -} - -static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) -{ - return pkt_hdr->p.parsed_layers != LAYER_ALL; -} - /* Forward declarations */ int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt); -/* Fill in parser metadata for L2 */ -static inline void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len) -{ - /* Packet alloc or reset have already init other offsets and flags */ - - /* We only support Ethernet for now */ - prs->input_flags.eth = 1; - - /* Detect jumbo frames */ - if (frame_len > _ODP_ETH_LEN_MAX) - prs->input_flags.jumbo = 1; - - /* Assume valid L2 header, no CRC/FCS check in SW */ - prs->input_flags.l2 = 1; - - prs->input_flags.parsed_l2 = 1; -} +/* Perform packet parse up to a given protocol layer */ +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, + odp_pktio_parser_layer_t layer); -static inline void _odp_packet_reset_parse(odp_packet_t pkt) +/* Reset parser metadata for a new parse */ +static inline void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) { - odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - - uint32_t frame_len = rte_pktmbuf_pkt_len(&pkt_hdr->buf_hdr.mb); - - pkt_hdr->p.parsed_layers = LAYER_NONE; - pkt_hdr->p.input_flags.all = 0; + /* Reset parser metadata before new parse */ + pkt_hdr->p.error_flags.all = 0; + pkt_hdr->p.input_flags.all = 0; pkt_hdr->p.output_flags.all = 0; - pkt_hdr->p.error_flags.all = 0; - pkt_hdr->p.l2_offset = 0; - - packet_parse_l2(&pkt_hdr->p, frame_len); + pkt_hdr->p.l2_offset = 0; + pkt_hdr->p.l3_offset = ODP_PACKET_OFFSET_INVALID; + pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID; } -/* Perform packet parse up to a given protocol layer */ -int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer); - -/* Reset parser metadata for a new parse */ -void packet_parse_reset(odp_packet_hdr_t *pkt_hdr); - /* Convert a packet handle to a buffer handle */ odp_buffer_t _odp_packet_to_buffer(odp_packet_t pkt); @@ -277,7 +224,9 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts) } int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr, - uint32_t pkt_len, uint32_t seg_len, layer_t layer); + uint32_t pkt_len, uint32_t seg_len, + odp_pktio_parser_layer_t layer); + /* We can't enforce tailroom reservation for received packets */ ODP_STATIC_ASSERT(CONFIG_PACKET_TAILROOM == 0, diff --git a/platform/linux-dpdk/include/odp_time_internal.h b/platform/linux-dpdk/include/odp_time_internal.h deleted file mode 100644 index 8cbf81419..000000000 --- a/platform/linux-dpdk/include/odp_time_internal.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2016, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/** - * @file - * - * ODP time service - */ - -#ifndef ODP_TIME_INTERNAL_H_ -#define ODP_TIME_INTERNAL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint64_t (*time_to_ns_fn) (odp_time_t time); -typedef odp_time_t (*time_diff_fn) (odp_time_t t2, odp_time_t t1); -typedef odp_time_t (*time_curr_fn)(void); -typedef int (*time_cmp_fn) (odp_time_t t2, odp_time_t t1); -typedef odp_time_t (*time_sum_fn) (odp_time_t t1, odp_time_t t2); -typedef odp_time_t (*time_local_from_ns_fn) (uint64_t ns); -typedef uint64_t (*time_local_res_fn)(void); -typedef uint64_t (*time_to_u64_fn) (odp_time_t time); - -typedef struct time_handler_ { - time_to_ns_fn time_to_ns; - time_diff_fn time_diff; - time_curr_fn time_curr; - time_cmp_fn time_cmp; - time_sum_fn time_sum; - time_local_from_ns_fn time_local_from_ns; - time_local_res_fn time_local_res; - time_to_u64_fn time_to_u64; -} time_handler_t; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/platform/linux-dpdk/m4/configure.m4 b/platform/linux-dpdk/m4/configure.m4 index fb9a91399..230ef6eff 100644 --- a/platform/linux-dpdk/m4/configure.m4 +++ b/platform/linux-dpdk/m4/configure.m4 @@ -28,6 +28,51 @@ AC_LINK_IFELSE( echo "Use newer version. For gcc > 4.7.0" exit -1) +dnl Check whether -latomic is needed +use_libatomic=no + +AC_MSG_CHECKING(whether -latomic is needed for 64-bit atomic built-ins) +AC_LINK_IFELSE( + [AC_LANG_SOURCE([[ + static int loc; + int main(void) + { + int prev = __atomic_exchange_n(&loc, 7, __ATOMIC_RELAXED); + return 0; + } + ]])], + [AC_MSG_RESULT(no)], + [AC_MSG_RESULT(yes) + AC_CHECK_LIB( + [atomic], [__atomic_exchange_8], + [use_libatomic=yes], + [AC_MSG_CHECKING([__atomic_exchange_8 is not available])]) + ]) + +AC_MSG_CHECKING(whether -latomic is needed for 128-bit atomic built-ins) +AC_LINK_IFELSE( + [AC_LANG_SOURCE([[ + static __int128 loc; + int main(void) + { + __int128 prev; + prev = __atomic_exchange_n(&loc, 7, __ATOMIC_RELAXED); + return 0; + } + ]])], + [AC_MSG_RESULT(no)], + [AC_MSG_RESULT(yes) + AC_CHECK_LIB( + [atomic], [__atomic_exchange_16], + [use_libatomic=yes], + [AC_MSG_CHECKING([cannot detect support for 128-bit atomics])]) + ]) + +if test "x$use_libatomic" = "xyes"; then + ATOMIC_LIBS="-latomic" +fi +AC_SUBST([ATOMIC_LIBS]) + # linux-generic PCAP support is not relevant as the code doesn't use # linux-generic pktio at all. And DPDK has its own PCAP support anyway AM_CONDITIONAL([HAVE_PCAP], [false]) diff --git a/platform/linux-dpdk/odp_crypto.c b/platform/linux-dpdk/odp_crypto.c index e1f7026ed..d95b15780 100644 --- a/platform/linux-dpdk/odp_crypto.c +++ b/platform/linux-dpdk/odp_crypto.c @@ -94,13 +94,15 @@ static int cipher_alg_odp_to_rte(odp_cipher_alg_t cipher_alg, cipher_xform->cipher.algo = RTE_CRYPTO_CIPHER_3DES_CBC; break; case ODP_CIPHER_ALG_AES_CBC: - /* deprecated */ +#if ODP_DEPRECATED_API case ODP_CIPHER_ALG_AES128_CBC: +#endif cipher_xform->cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC; break; case ODP_CIPHER_ALG_AES_GCM: - /* deprecated */ +#if ODP_DEPRECATED_API case ODP_CIPHER_ALG_AES128_GCM: +#endif cipher_xform->cipher.algo = RTE_CRYPTO_CIPHER_AES_GCM; break; default: @@ -121,20 +123,31 @@ static int auth_alg_odp_to_rte(odp_auth_alg_t auth_alg, auth_xform->auth.algo = RTE_CRYPTO_AUTH_NULL; break; case ODP_AUTH_ALG_MD5_HMAC: - /* deprecated */ +#if ODP_DEPRECATED_API case ODP_AUTH_ALG_MD5_96: +#endif auth_xform->auth.algo = RTE_CRYPTO_AUTH_MD5_HMAC; auth_xform->auth.digest_length = 12; break; case ODP_AUTH_ALG_SHA256_HMAC: - /* deprecated */ +#if ODP_DEPRECATED_API case ODP_AUTH_ALG_SHA256_128: +#endif auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA256_HMAC; auth_xform->auth.digest_length = 16; break; + case ODP_AUTH_ALG_SHA1_HMAC: + auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC; + auth_xform->auth.digest_length = 20; + break; + case ODP_AUTH_ALG_SHA512_HMAC: + auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA512_HMAC; + auth_xform->auth.digest_length = 64; + break; case ODP_AUTH_ALG_AES_GCM: - /* deprecated */ +#if ODP_DEPRECATED_API case ODP_AUTH_ALG_AES128_GCM: +#endif auth_xform->auth.algo = RTE_CRYPTO_AUTH_AES_GCM; auth_xform->auth.digest_length = 16; break; @@ -151,8 +164,10 @@ static crypto_session_entry_t *alloc_session(void) odp_spinlock_lock(&global->lock); session = global->free; - if (session) + if (session) { global->free = session->next; + session->next = NULL; + } odp_spinlock_unlock(&global->lock); return session; @@ -349,14 +364,16 @@ int odp_crypto_capability(odp_crypto_capability_t *capability) if (cap_cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC) { hw_ciphers->bit.aes_cbc = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API hw_ciphers->bit.aes128_cbc = 1; +#endif } if (cap_cipher_algo == RTE_CRYPTO_CIPHER_AES_GCM) { hw_ciphers->bit.aes_gcm = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API hw_ciphers->bit.aes128_gcm = 1; +#endif } } @@ -373,20 +390,31 @@ int odp_crypto_capability(odp_crypto_capability_t *capability) if (cap_auth_algo == RTE_CRYPTO_AUTH_AES_GCM) { hw_auths->bit.aes_gcm = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API hw_auths->bit.aes128_gcm = 1; +#endif } if (cap_auth_algo == RTE_CRYPTO_AUTH_MD5_HMAC) { hw_auths->bit.md5_hmac = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API hw_auths->bit.md5_96 = 1; +#endif } if (cap_auth_algo == RTE_CRYPTO_AUTH_SHA256_HMAC) { hw_auths->bit.sha256_hmac = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API hw_auths->bit.sha256_128 = 1; +#endif + } + if (cap_auth_algo == + RTE_CRYPTO_AUTH_SHA1_HMAC) { + hw_auths->bit.sha1_hmac = 1; + } + if (cap_auth_algo == + RTE_CRYPTO_AUTH_SHA512_HMAC) { + hw_auths->bit.sha512_hmac = 1; } } cap = &dev_info.capabilities[++i]; @@ -411,14 +439,16 @@ int odp_crypto_capability(odp_crypto_capability_t *capability) if (cap_cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC) { ciphers->bit.aes_cbc = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API ciphers->bit.aes128_cbc = 1; +#endif } if (cap_cipher_algo == RTE_CRYPTO_CIPHER_AES_GCM) { ciphers->bit.aes_gcm = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API ciphers->bit.aes128_gcm = 1; +#endif } } @@ -435,20 +465,31 @@ int odp_crypto_capability(odp_crypto_capability_t *capability) if (cap_auth_algo == RTE_CRYPTO_AUTH_AES_GCM) { auths->bit.aes_gcm = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API auths->bit.aes128_gcm = 1; +#endif } if (cap_auth_algo == RTE_CRYPTO_AUTH_MD5_HMAC) { auths->bit.md5_hmac = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API auths->bit.md5_96 = 1; +#endif } if (cap_auth_algo == RTE_CRYPTO_AUTH_SHA256_HMAC) { auths->bit.sha256_hmac = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API auths->bit.sha256_128 = 1; +#endif + } + if (cap_auth_algo == + RTE_CRYPTO_AUTH_SHA1_HMAC) { + auths->bit.sha1_hmac = 1; + } + if (cap_auth_algo == + RTE_CRYPTO_AUTH_SHA512_HMAC) { + auths->bit.sha512_hmac = 1; } } cap = &dev_info.capabilities[++i]; @@ -547,7 +588,7 @@ int odp_crypto_cipher_capability(odp_cipher_alg_t cipher, int odp_crypto_auth_capability(odp_auth_alg_t auth, odp_crypto_auth_capability_t dst[], - int num_copy) + int num_copy) { odp_crypto_auth_capability_t src[num_copy]; int idx = 0, rc = 0; @@ -740,7 +781,7 @@ static int get_crypto_dev(struct rte_crypto_sym_xform *cipher_xform, return -1; } -int odp_crypto_session_create(odp_crypto_session_params_t *params, +int odp_crypto_session_create(odp_crypto_session_param_t *param, odp_crypto_session_t *session_out, odp_crypto_ses_create_err_t *status) { @@ -771,7 +812,7 @@ int odp_crypto_session_create(odp_crypto_session_params_t *params, /* Cipher Data */ cipher_xform.cipher.key.data = rte_malloc("crypto key", - params->cipher_key.length, 0); + param->cipher_key.length, 0); if (cipher_xform.cipher.key.data == NULL) { ODP_ERR("Failed to allocate memory for cipher key\n"); /* remove the crypto_session_entry_t */ @@ -782,14 +823,14 @@ int odp_crypto_session_create(odp_crypto_session_params_t *params, cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; cipher_xform.next = NULL; - cipher_xform.cipher.key.length = params->cipher_key.length; + cipher_xform.cipher.key.length = param->cipher_key.length; memcpy(cipher_xform.cipher.key.data, - params->cipher_key.data, - params->cipher_key.length); + param->cipher_key.data, + param->cipher_key.length); /* Authentication Data */ auth_xform.auth.key.data = rte_malloc("auth key", - params->auth_key.length, 0); + param->auth_key.length, 0); if (auth_xform.auth.key.data == NULL) { ODP_ERR("Failed to allocate memory for auth key\n"); /* remove the crypto_session_entry_t */ @@ -799,16 +840,16 @@ int odp_crypto_session_create(odp_crypto_session_params_t *params, } auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH; auth_xform.next = NULL; - auth_xform.auth.key.length = params->auth_key.length; + auth_xform.auth.key.length = param->auth_key.length; memcpy(auth_xform.auth.key.data, - params->auth_key.data, - params->auth_key.length); + param->auth_key.data, + param->auth_key.length); /* Derive order */ - if (ODP_CRYPTO_OP_ENCODE == params->op) - entry->do_cipher_first = params->auth_cipher_text; + if (ODP_CRYPTO_OP_ENCODE == param->op) + entry->do_cipher_first = param->auth_cipher_text; else - entry->do_cipher_first = !params->auth_cipher_text; + entry->do_cipher_first = !param->auth_cipher_text; /* Process based on cipher */ /* Derive order */ @@ -824,7 +865,7 @@ int odp_crypto_session_create(odp_crypto_session_params_t *params, first_xform->next = &cipher_xform; } - rc = cipher_alg_odp_to_rte(params->cipher_alg, &cipher_xform); + rc = cipher_alg_odp_to_rte(param->cipher_alg, &cipher_xform); /* Check result */ if (rc) { @@ -832,7 +873,7 @@ int odp_crypto_session_create(odp_crypto_session_params_t *params, return -1; } - rc = auth_alg_odp_to_rte(params->auth_alg, &auth_xform); + rc = auth_alg_odp_to_rte(param->auth_alg, &auth_xform); /* Check result */ if (rc) { @@ -845,7 +886,7 @@ int odp_crypto_session_create(odp_crypto_session_params_t *params, rc = get_crypto_dev(&cipher_xform, &auth_xform, - params->iv.length, + param->iv.length, &cdev_id); if (rc) { @@ -868,10 +909,10 @@ int odp_crypto_session_create(odp_crypto_session_params_t *params, entry->rte_session = (intptr_t)session; entry->cipher_xform = cipher_xform; entry->auth_xform = auth_xform; - entry->iv.length = params->iv.length; - entry->iv.data = params->iv.data; - entry->output_pool = params->output_pool; - entry->compl_queue = params->compl_queue; + entry->iv.length = param->iv.length; + entry->iv.data = param->iv.data; + entry->output_pool = param->output_pool; + entry->compl_queue = param->compl_queue; /* We're happy */ *session_out = (intptr_t)entry; @@ -903,7 +944,7 @@ int odp_crypto_session_destroy(odp_crypto_session_t session) return 0; } -int odp_crypto_operation(odp_crypto_op_params_t *params, +int odp_crypto_operation(odp_crypto_op_param_t *param, odp_bool_t *posted, odp_crypto_op_result_t *result) { @@ -917,10 +958,10 @@ int odp_crypto_operation(odp_crypto_op_params_t *params, uint8_t *data_addr, *aad_head; struct rte_crypto_op *op; uint16_t rc; - uint32_t plain_len, aad_len; - odp_bool_t pkt_allocated = 0; + uint32_t aad_len; + odp_bool_t allocated = false; - entry = (crypto_session_entry_t *)(intptr_t)params->session; + entry = (crypto_session_entry_t *)(intptr_t)param->session; if (entry == NULL) return -1; @@ -935,71 +976,71 @@ int odp_crypto_operation(odp_crypto_op_params_t *params, auth_xform = entry->auth_xform; /* Resolve output buffer */ - if (ODP_PACKET_INVALID == params->out_pkt && + if (ODP_PACKET_INVALID == param->out_pkt && ODP_POOL_INVALID != entry->output_pool) { - params->out_pkt = odp_packet_alloc(entry->output_pool, - odp_packet_len(params->pkt)); - pkt_allocated = 1; + param->out_pkt = odp_packet_alloc(entry->output_pool, + odp_packet_len(param->pkt)); + allocated = true; } - if (params->pkt != params->out_pkt) { - if (odp_unlikely(ODP_PACKET_INVALID == params->out_pkt)) + if (param->pkt != param->out_pkt) { + if (odp_unlikely(ODP_PACKET_INVALID == param->out_pkt)) ODP_ABORT(); - (void)odp_packet_copy_from_pkt(params->out_pkt, + int ret; + + ret = odp_packet_copy_from_pkt(param->out_pkt, 0, - params->pkt, + param->pkt, 0, - odp_packet_len(params->pkt)); - _odp_packet_copy_md_to_packet(params->pkt, params->out_pkt); - odp_packet_free(params->pkt); - params->pkt = ODP_PACKET_INVALID; + odp_packet_len(param->pkt)); + if (odp_unlikely(ret < 0)) + goto err; + + _odp_packet_copy_md_to_packet(param->pkt, param->out_pkt); + odp_packet_free(param->pkt); + param->pkt = ODP_PACKET_INVALID; } - data_addr = odp_packet_data(params->out_pkt); + data_addr = odp_packet_data(param->out_pkt); odp_spinlock_init(&global->lock); odp_spinlock_lock(&global->lock); op = rte_crypto_op_alloc(global->crypto_op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC); if (op == NULL) { - if (pkt_allocated) - odp_packet_free(params->out_pkt); ODP_ERR("Failed to allocate crypto operation"); - return -1; + goto err; } odp_spinlock_unlock(&global->lock); /* Set crypto operation data parameters */ rte_crypto_op_attach_sym_session(op, rte_session); - op->sym->auth.digest.data = data_addr + params->hash_result_offset; + op->sym->auth.digest.data = data_addr + param->hash_result_offset; op->sym->auth.digest.phys_addr = - rte_pktmbuf_mtophys_offset((struct rte_mbuf *)params->out_pkt, - odp_packet_len(params->out_pkt) - + rte_pktmbuf_mtophys_offset((struct rte_mbuf *)param->out_pkt, + odp_packet_len(param->out_pkt) - auth_xform.auth.digest_length); op->sym->auth.digest.length = auth_xform.auth.digest_length; /* For SNOW3G algorithms, offset/length must be in bits */ if (auth_xform.auth.algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2) { - op->sym->auth.data.offset = params->auth_range.offset << 3; - op->sym->auth.data.length = params->auth_range.length << 3; + op->sym->auth.data.offset = param->auth_range.offset << 3; + op->sym->auth.data.length = param->auth_range.length << 3; } else { - op->sym->auth.data.offset = params->auth_range.offset; - op->sym->auth.data.length = params->auth_range.length; + op->sym->auth.data.offset = param->auth_range.offset; + op->sym->auth.data.length = param->auth_range.length; } - aad_head = data_addr + params->auth_range.offset; - plain_len = params->cipher_range.length; - aad_len = params->auth_range.length - plain_len; + aad_head = param->aad.ptr; + aad_len = param->aad.length; if (aad_len > 0) { op->sym->auth.aad.data = rte_malloc("aad", aad_len, 0); if (op->sym->auth.aad.data == NULL) { rte_crypto_op_free(op); - if (pkt_allocated) - odp_packet_free(params->out_pkt); ODP_ERR("Failed to allocate memory for AAD"); - return -1; + goto err; } memcpy(op->sym->auth.aad.data, aad_head, aad_len); @@ -1010,24 +1051,20 @@ int odp_crypto_operation(odp_crypto_op_params_t *params, if (entry->iv.length == 0) { rte_crypto_op_free(op); - if (pkt_allocated) - odp_packet_free(params->out_pkt); ODP_ERR("Wrong IV length"); - return -1; + goto err; } op->sym->cipher.iv.data = rte_malloc("iv", entry->iv.length, 0); if (op->sym->cipher.iv.data == NULL) { rte_crypto_op_free(op); - if (pkt_allocated) - odp_packet_free(params->out_pkt); ODP_ERR("Failed to allocate memory for IV"); - return -1; + goto err; } - if (params->override_iv_ptr) { + if (param->override_iv_ptr) { memcpy(op->sym->cipher.iv.data, - params->override_iv_ptr, + param->override_iv_ptr, entry->iv.length); } else if (entry->iv.data) { memcpy(op->sym->cipher.iv.data, @@ -1043,27 +1080,25 @@ int odp_crypto_operation(odp_crypto_op_params_t *params, /* For SNOW3G algorithms, offset/length must be in bits */ if (cipher_xform.cipher.algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2) { - op->sym->cipher.data.offset = params->cipher_range.offset << 3; - op->sym->cipher.data.length = params->cipher_range.length << 3; + op->sym->cipher.data.offset = param->cipher_range.offset << 3; + op->sym->cipher.data.length = param->cipher_range.length << 3; } else { - op->sym->cipher.data.offset = params->cipher_range.offset; - op->sym->cipher.data.length = params->cipher_range.length; + op->sym->cipher.data.offset = param->cipher_range.offset; + op->sym->cipher.data.length = param->cipher_range.length; } if (rc_cipher == ODP_CRYPTO_ALG_ERR_NONE && rc_auth == ODP_CRYPTO_ALG_ERR_NONE) { int queue_pair = odp_cpu_id(); - op->sym->m_src = (struct rte_mbuf *)params->out_pkt; + op->sym->m_src = (struct rte_mbuf *)param->out_pkt; rc = rte_cryptodev_enqueue_burst(rte_session->dev_id, queue_pair, &op, 1); if (rc == 0) { rte_crypto_op_free(op); - if (pkt_allocated) - odp_packet_free(params->out_pkt); ODP_ERR("Failed to enqueue packet"); - return -1; + goto err; } rc = rte_cryptodev_dequeue_burst(rte_session->dev_id, @@ -1071,18 +1106,16 @@ int odp_crypto_operation(odp_crypto_op_params_t *params, if (rc == 0) { rte_crypto_op_free(op); - if (pkt_allocated) - odp_packet_free(params->out_pkt); ODP_ERR("Failed to dequeue packet"); - return -1; + goto err; } - params->out_pkt = (odp_packet_t)op->sym->m_src; + param->out_pkt = (odp_packet_t)op->sym->m_src; } /* Fill in result */ - local_result.ctx = params->ctx; - local_result.pkt = params->out_pkt; + local_result.ctx = param->ctx; + local_result.pkt = param->out_pkt; local_result.cipher_status.alg_err = rc_cipher; local_result.cipher_status.hw_err = ODP_CRYPTO_HW_ERR_NONE; local_result.auth_status.alg_err = rc_auth; @@ -1098,7 +1131,7 @@ int odp_crypto_operation(odp_crypto_op_params_t *params, odp_event_t completion_event; odp_crypto_generic_op_result_t *op_result; - completion_event = odp_packet_to_event(params->out_pkt); + completion_event = odp_packet_to_event(param->out_pkt); _odp_buffer_event_type_set( odp_buffer_from_event(completion_event), ODP_EVENT_CRYPTO_COMPL); @@ -1108,7 +1141,7 @@ int odp_crypto_operation(odp_crypto_op_params_t *params, op_result->result = local_result; if (odp_queue_enq(entry->compl_queue, completion_event)) { odp_event_free(completion_event); - return -1; + goto err; } /* Indicate to caller operation was async */ @@ -1116,14 +1149,21 @@ int odp_crypto_operation(odp_crypto_op_params_t *params, } else { /* Synchronous, simply return results */ if (!result) - return -1; + goto err; *result = local_result; /* Indicate to caller operation was sync */ *posted = 0; } - return 0; + +err: + if (allocated) { + odp_packet_free(param->out_pkt); + param->out_pkt = ODP_PACKET_INVALID; + } + + return -1; } int odp_crypto_term_global(void) diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c index 68ad26b29..0d05e23f2 100644 --- a/platform/linux-dpdk/odp_packet.c +++ b/platform/linux-dpdk/odp_packet.c @@ -21,6 +21,8 @@ #include <stddef.h> #include <inttypes.h> +#include <odp/visibility_begin.h> + /* Fill in packet header field offsets for inline functions */ const _odp_packet_inline_offset_t _odp_packet_inline ODP_ALIGNED_CACHE = { @@ -49,6 +51,8 @@ const _odp_packet_inline_offset_t _odp_packet_inline ODP_ALIGNED_CACHE = { .rss_flag = PKT_RX_RSS_HASH }; +#include <odp/visibility_end.h> + struct rte_mbuf dummy; ODP_STATIC_ASSERT(sizeof(dummy.data_off) == sizeof(uint16_t), "data_off should be uint16_t"); @@ -77,24 +81,6 @@ static inline odp_packet_hdr_t *buf_to_packet_hdr(odp_buffer_t buf) return (odp_packet_hdr_t *)buf_hdl_to_hdr(buf); } -static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr) -{ - pkt_hdr->p.input_flags.parsed_l2 = 1; - pkt_hdr->p.parsed_layers = LAYER_ALL; -} - -void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) -{ - /* Reset parser metadata before new parse */ - pkt_hdr->p.parsed_layers = LAYER_NONE; - pkt_hdr->p.error_flags.all = 0; - pkt_hdr->p.input_flags.all = 0; - pkt_hdr->p.output_flags.all = 0; - pkt_hdr->p.l2_offset = 0; - pkt_hdr->p.l3_offset = ODP_PACKET_OFFSET_INVALID; - pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID; -} - static odp_packet_t packet_alloc(pool_entry_t* pool, uint32_t len) { odp_packet_t pkt; @@ -194,7 +180,6 @@ int odp_packet_reset(odp_packet_t pkt, uint32_t len) return -1; } - pkt_hdr->p.parsed_layers = LAYER_NONE; pkt_hdr->p.input_flags.all = 0; pkt_hdr->p.output_flags.all = 0; pkt_hdr->p.error_flags.all = 0; @@ -207,9 +192,6 @@ int odp_packet_reset(odp_packet_t pkt, uint32_t len) pkt_hdr->input = ODP_PKTIO_INVALID; - /* Disable lazy parsing on user allocated packets */ - packet_parse_disable(pkt_hdr); - mb->port = 0xff; mb->pkt_len = len; mb->data_off = RTE_PKTMBUF_HEADROOM; @@ -623,8 +605,6 @@ void *odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L3) - packet_parse_layer(pkt_hdr, LAYER_L3); return packet_offset_to_ptr(pkt, len, pkt_hdr->p.l3_offset); } @@ -632,8 +612,6 @@ uint32_t odp_packet_l3_offset(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L3) - packet_parse_layer(pkt_hdr, LAYER_L3); return pkt_hdr->p.l3_offset; } @@ -644,8 +622,6 @@ int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset) if (odp_unlikely(offset >= (odp_packet_len(pkt) - 1))) return -1; - if (pkt_hdr->p.parsed_layers < LAYER_L3) - packet_parse_layer(pkt_hdr, LAYER_L3); pkt_hdr->p.l3_offset = offset; return 0; } @@ -654,8 +630,6 @@ void *odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L4) - packet_parse_layer(pkt_hdr, LAYER_L4); return packet_offset_to_ptr(pkt, len, pkt_hdr->p.l4_offset); } @@ -663,8 +637,6 @@ uint32_t odp_packet_l4_offset(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L4) - packet_parse_layer(pkt_hdr, LAYER_L4); return pkt_hdr->p.l4_offset; } @@ -675,8 +647,6 @@ int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset) if (odp_unlikely(offset >= (odp_packet_len(pkt) - 1))) return -1; - if (pkt_hdr->p.parsed_layers < LAYER_L4) - packet_parse_layer(pkt_hdr, LAYER_L4); pkt_hdr->p.l4_offset = offset; return 0; } @@ -1148,12 +1118,11 @@ static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, uint8_t ihl = _ODP_IPV4HDR_IHL(ipv4->ver_ihl); uint16_t frag_offset; uint32_t dstaddr = odp_be_to_cpu_32(ipv4->dst_addr); - - prs->l3_len = odp_be_to_cpu_16(ipv4->tot_len); + uint32_t l3_len = odp_be_to_cpu_16(ipv4->tot_len); if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN) || odp_unlikely(ver != 4) || - (prs->l3_len > frame_len - *offset)) { + (l3_len > frame_len - *offset)) { prs->error_flags.ip_err = 1; return 0; } @@ -1190,13 +1159,12 @@ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr; const _odp_ipv6hdr_ext_t *ipv6ext; uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr.u8[0]); - - prs->l3_len = odp_be_to_cpu_16(ipv6->payload_len) + - _ODP_IPV6HDR_LEN; + uint32_t l3_len = odp_be_to_cpu_16(ipv6->payload_len) + + _ODP_IPV6HDR_LEN; /* Basic sanity checks on IPv6 header */ if ((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || - prs->l3_len > frame_len - *offset) { + l3_len > frame_len - *offset) { prs->error_flags.ip_err = 1; return 0; } @@ -1257,9 +1225,6 @@ static inline void parse_tcp(packet_parser_t *prs, else if ((uint32_t)tcp->hl * 4 > sizeof(_odp_tcphdr_t)) prs->input_flags.tcpopt = 1; - prs->l4_len = prs->l3_len + - prs->l3_offset - prs->l4_offset; - if (offset) *offset += (uint32_t)tcp->hl * 4; *parseptr += (uint32_t)tcp->hl * 4; @@ -1274,13 +1239,8 @@ static inline void parse_udp(packet_parser_t *prs, const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr; uint32_t udplen = odp_be_to_cpu_16(udp->length); - if (udplen < sizeof(_odp_udphdr_t) || - udplen > (prs->l3_len + - prs->l4_offset - prs->l3_offset)) { + if (odp_unlikely(udplen < sizeof(_odp_udphdr_t))) prs->error_flags.udp_err = 1; - } - - prs->l4_len = udplen; if (offset) *offset += sizeof(_odp_udphdr_t); @@ -1294,197 +1254,172 @@ static inline void parse_udp(packet_parser_t *prs, * available from the ptr. */ int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, - uint32_t frame_len, uint32_t seg_len, layer_t layer) + uint32_t frame_len, uint32_t seg_len, + odp_pktio_parser_layer_t layer) { uint32_t offset; + uint16_t ethtype; const uint8_t *parseptr; + uint8_t ip_proto; + const _odp_ethhdr_t *eth; + uint16_t macaddr0, macaddr2, macaddr4; + const _odp_vlanhdr_t *vlan; - switch (prs->parsed_layers) { - case LAYER_NONE: - /* Fall through */ + if (layer == ODP_PKTIO_PARSER_LAYER_NONE) + return 0; - case LAYER_L2: - { - const _odp_ethhdr_t *eth; - uint16_t macaddr0, macaddr2, macaddr4; - const _odp_vlanhdr_t *vlan; - - offset = sizeof(_odp_ethhdr_t); - if (packet_parse_l2_not_done(prs)) - packet_parse_l2(prs, frame_len); - - eth = (const _odp_ethhdr_t *)ptr; - - /* Handle Ethernet broadcast/multicast addresses */ - macaddr0 = odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth)); - prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; - - if (macaddr0 == 0xffff) { - macaddr2 = - odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth + 1)); - macaddr4 = - odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth + 2)); - prs->input_flags.eth_bcast = - (macaddr2 == 0xffff) && (macaddr4 == 0xffff); - } else { - prs->input_flags.eth_bcast = 0; - } + /* We only support Ethernet for now */ + prs->input_flags.eth = 1; + /* Assume valid L2 header, no CRC/FCS check in SW */ + prs->input_flags.l2 = 1; + /* Detect jumbo frames */ + if (frame_len > _ODP_ETH_LEN_MAX) + prs->input_flags.jumbo = 1; + + offset = sizeof(_odp_ethhdr_t); + eth = (const _odp_ethhdr_t *)ptr; + + /* Handle Ethernet broadcast/multicast addresses */ + macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth)); + prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; + + if (macaddr0 == 0xffff) { + macaddr2 = + odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 1)); + macaddr4 = + odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 2)); + prs->input_flags.eth_bcast = + (macaddr2 == 0xffff) && (macaddr4 == 0xffff); + } else { + prs->input_flags.eth_bcast = 0; + } - /* Get Ethertype */ - prs->ethtype = odp_be_to_cpu_16(eth->type); - parseptr = (const uint8_t *)(eth + 1); + /* Get Ethertype */ + ethtype = odp_be_to_cpu_16(eth->type); + parseptr = (const uint8_t *)(eth + 1); - /* Check for SNAP vs. DIX */ - if (prs->ethtype < _ODP_ETH_LEN_MAX) { - prs->input_flags.snap = 1; - if (prs->ethtype > frame_len - offset) { - prs->error_flags.snap_len = 1; - goto parse_exit; - } - prs->ethtype = odp_be_to_cpu_16(*((const uint16_t *) - (uintptr_t) - (parseptr + 6))); - offset += 8; - parseptr += 8; + /* Check for SNAP vs. DIX */ + if (ethtype < _ODP_ETH_LEN_MAX) { + prs->input_flags.snap = 1; + if (ethtype > frame_len - offset) { + prs->error_flags.snap_len = 1; + goto parse_exit; } + ethtype = odp_be_to_cpu_16(*((const uint16_t *)(uintptr_t) + (parseptr + 6))); + offset += 8; + parseptr += 8; + } - /* Parse the VLAN header(s), if present */ - if (prs->ethtype == _ODP_ETHTYPE_VLAN_OUTER) { - prs->input_flags.vlan_qinq = 1; - prs->input_flags.vlan = 1; - - vlan = (const _odp_vlanhdr_t *)parseptr; - prs->ethtype = odp_be_to_cpu_16(vlan->type); - offset += sizeof(_odp_vlanhdr_t); - parseptr += sizeof(_odp_vlanhdr_t); - } + /* Parse the VLAN header(s), if present */ + if (ethtype == _ODP_ETHTYPE_VLAN_OUTER) { + prs->input_flags.vlan_qinq = 1; + prs->input_flags.vlan = 1; - if (prs->ethtype == _ODP_ETHTYPE_VLAN) { - prs->input_flags.vlan = 1; - vlan = (const _odp_vlanhdr_t *)parseptr; - prs->ethtype = odp_be_to_cpu_16(vlan->type); - offset += sizeof(_odp_vlanhdr_t); - parseptr += sizeof(_odp_vlanhdr_t); - } + vlan = (const _odp_vlanhdr_t *)parseptr; + ethtype = odp_be_to_cpu_16(vlan->type); + offset += sizeof(_odp_vlanhdr_t); + parseptr += sizeof(_odp_vlanhdr_t); + } - prs->l3_offset = offset; - prs->parsed_layers = LAYER_L2; - if (layer == LAYER_L2) - return prs->error_flags.all != 0; + if (ethtype == _ODP_ETHTYPE_VLAN) { + prs->input_flags.vlan = 1; + vlan = (const _odp_vlanhdr_t *)parseptr; + ethtype = odp_be_to_cpu_16(vlan->type); + offset += sizeof(_odp_vlanhdr_t); + parseptr += sizeof(_odp_vlanhdr_t); } - /* Fall through */ - case LAYER_L3: - { - offset = prs->l3_offset; - parseptr = (const uint8_t *)(ptr + offset); - /* Set l3_offset+flag only for known ethtypes */ - prs->input_flags.l3 = 1; - - /* Parse Layer 3 headers */ - switch (prs->ethtype) { - case _ODP_ETHTYPE_IPV4: - prs->input_flags.ipv4 = 1; - prs->ip_proto = parse_ipv4(prs, &parseptr, &offset, - frame_len); - break; + if (layer == ODP_PKTIO_PARSER_LAYER_L2) + return prs->error_flags.all != 0; - case _ODP_ETHTYPE_IPV6: - prs->input_flags.ipv6 = 1; - prs->ip_proto = parse_ipv6(prs, &parseptr, &offset, - frame_len, seg_len); - break; + /* Set l3_offset+flag only for known ethtypes */ + prs->l3_offset = offset; + prs->input_flags.l3 = 1; - case _ODP_ETHTYPE_ARP: - prs->input_flags.arp = 1; - prs->ip_proto = 255; /* Reserved invalid by IANA */ - break; + /* Parse Layer 3 headers */ + switch (ethtype) { + case _ODP_ETHTYPE_IPV4: + prs->input_flags.ipv4 = 1; + ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len); + break; - default: - prs->input_flags.l3 = 0; - prs->l3_offset = ODP_PACKET_OFFSET_INVALID; - prs->ip_proto = 255; /* Reserved invalid by IANA */ - } + case _ODP_ETHTYPE_IPV6: + prs->input_flags.ipv6 = 1; + ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, + seg_len); + break; - /* Set l4_offset+flag only for known ip_proto */ - prs->l4_offset = offset; - prs->parsed_layers = LAYER_L3; - if (layer == LAYER_L3) - return prs->error_flags.all != 0; - } - /* Fall through */ + case _ODP_ETHTYPE_ARP: + prs->input_flags.arp = 1; + ip_proto = 255; /* Reserved invalid by IANA */ + break; - case LAYER_L4: - { - offset = prs->l4_offset; - parseptr = (const uint8_t *)(ptr + offset); - prs->input_flags.l4 = 1; + default: + prs->input_flags.l3 = 0; + prs->l3_offset = ODP_PACKET_OFFSET_INVALID; + ip_proto = 255; /* Reserved invalid by IANA */ + } - /* Parse Layer 4 headers */ - switch (prs->ip_proto) { - case _ODP_IPPROTO_ICMP: - prs->input_flags.icmp = 1; - break; + if (layer == ODP_PKTIO_PARSER_LAYER_L3) + return prs->error_flags.all != 0; - case _ODP_IPPROTO_TCP: - if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) - return -1; - prs->input_flags.tcp = 1; - parse_tcp(prs, &parseptr, NULL); - break; + /* Set l4_offset+flag only for known ip_proto */ + prs->l4_offset = offset; + prs->input_flags.l4 = 1; - case _ODP_IPPROTO_UDP: - if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) - return -1; - prs->input_flags.udp = 1; - parse_udp(prs, &parseptr, NULL); - break; + /* Parse Layer 4 headers */ + switch (ip_proto) { + case _ODP_IPPROTO_ICMPv4: + /* Fall through */ - case _ODP_IPPROTO_AH: - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_ah = 1; - break; + case _ODP_IPPROTO_ICMPv6: + prs->input_flags.icmp = 1; + break; - case _ODP_IPPROTO_ESP: - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_esp = 1; - break; + case _ODP_IPPROTO_TCP: + if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) + return -1; + prs->input_flags.tcp = 1; + parse_tcp(prs, &parseptr, NULL); + break; - case _ODP_IPPROTO_SCTP: - prs->input_flags.sctp = 1; - break; + case _ODP_IPPROTO_UDP: + if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) + return -1; + prs->input_flags.udp = 1; + parse_udp(prs, &parseptr, NULL); + break; - default: - prs->input_flags.l4 = 0; - prs->l4_offset = ODP_PACKET_OFFSET_INVALID; - break; - } + case _ODP_IPPROTO_AH: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_ah = 1; + break; - prs->parsed_layers = LAYER_L4; + case _ODP_IPPROTO_ESP: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_esp = 1; break; - } - case LAYER_ALL: + case _ODP_IPPROTO_SCTP: + prs->input_flags.sctp = 1; break; default: - ODP_ERR("Invalid parse layer: %d\n", (int)layer); - return -1; + prs->input_flags.l4 = 0; + prs->l4_offset = ODP_PACKET_OFFSET_INVALID; + break; } - - prs->parsed_layers = LAYER_ALL; - parse_exit: return prs->error_flags.all != 0; } - /** * Simple packet parser */ -int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer) +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, + odp_pktio_parser_layer_t layer) { uint32_t seg_len = odp_packet_seg_len((odp_packet_t)pkt_hdr); uint32_t len = packet_len(pkt_hdr); diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c index 26d32370b..d056a8242 100644 --- a/platform/linux-dpdk/odp_packet_dpdk.c +++ b/platform/linux-dpdk/odp_packet_dpdk.c @@ -369,6 +369,12 @@ static int recv_pkt_dpdk(pktio_entry_t *pktio_entry, int index, (struct rte_mbuf **)pkt_table, (uint16_t)RTE_MAX(len, min)); + if (pktio_entry->s.config.pktin.bit.ts_all || + pktio_entry->s.config.pktin.bit.ts_ptp) { + ts_val = odp_time_global(); + ts = &ts_val; + } + if (nb_rx == 0 && !pkt_dpdk->lockless_tx) { pool_entry_t *pool_entry = get_pool_entry(_odp_typeval(pktio_entry->s.pool)); @@ -382,14 +388,16 @@ static int recv_pkt_dpdk(pktio_entry_t *pktio_entry, int index, odp_ticketlock_unlock(&pkt_dpdk->rx_lock[index]); for (i = 0; i < nb_rx; ++i) { - _odp_packet_reset_parse(pkt_table[i]); - odp_packet_hdr(pkt_table[i])->input = pktio_entry->s.handle; - } + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt_table[i]); - if (pktio_entry->s.config.pktin.bit.ts_all || - pktio_entry->s.config.pktin.bit.ts_ptp) { - ts_val = odp_time_global(); - ts = &ts_val; + packet_parse_reset(pkt_hdr); + pkt_hdr->input = pktio_entry->s.handle; + + if (!pktio_cls_enabled(pktio_entry) && + pktio_entry->s.config.parser.layer) + packet_parse_layer(pkt_hdr, + pktio_entry->s.config.parser.layer); + packet_set_ts(pkt_hdr, ts); } if (odp_unlikely(min > len)) { diff --git a/platform/linux-dpdk/odp_packet_flags.c b/platform/linux-dpdk/odp_packet_flags.c index 20517e164..d8c68f021 100644 --- a/platform/linux-dpdk/odp_packet_flags.c +++ b/platform/linux-dpdk/odp_packet_flags.c @@ -8,26 +8,21 @@ #include <odp/api/packet_flags.h> #include <odp_packet_internal.h> -#define retflag(pkt, x, layer) do { \ +#define retflag(pkt, x) do { \ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); \ - if (pkt_hdr->p.parsed_layers < layer) \ - packet_parse_layer(pkt_hdr, layer); \ return pkt_hdr->p.x; \ } while (0) -#define setflag(pkt, x, v, layer) do { \ +#define setflag(pkt, x, v) do { \ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); \ - if (pkt_hdr->p.parsed_layers < layer) \ - packet_parse_layer(pkt_hdr, layer); \ - pkt_hdr->p.x = v & 1; \ + pkt_hdr->p.x = (v) & 1; \ } while (0) int odp_packet_has_error(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - return odp_packet_hdr(pkt)->p.error_flags.all != 0; + + return pkt_hdr->p.error_flags.all != 0; } /* Get Input Flags */ @@ -44,126 +39,117 @@ int odp_packet_has_l2_error(odp_packet_t pkt) int odp_packet_has_l3(odp_packet_t pkt) { - retflag(pkt, input_flags.l3, LAYER_L3); + retflag(pkt, input_flags.l3); } int odp_packet_has_l3_error(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - return pkt_hdr->p.error_flags.ip_err; } int odp_packet_has_l4(odp_packet_t pkt) { - retflag(pkt, input_flags.l4, LAYER_L4); + retflag(pkt, input_flags.l4); } int odp_packet_has_l4_error(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L4) - packet_parse_layer(pkt_hdr, LAYER_L4); - return pkt_hdr->p.error_flags.tcp_err | pkt_hdr->p.error_flags.udp_err; } int odp_packet_has_eth_bcast(odp_packet_t pkt) { - retflag(pkt, input_flags.eth_bcast, LAYER_L2); + retflag(pkt, input_flags.eth_bcast); } int odp_packet_has_eth_mcast(odp_packet_t pkt) { - retflag(pkt, input_flags.eth_mcast, LAYER_L2); + retflag(pkt, input_flags.eth_mcast); } int odp_packet_has_vlan(odp_packet_t pkt) { - retflag(pkt, input_flags.vlan, LAYER_L2); + retflag(pkt, input_flags.vlan); } int odp_packet_has_vlan_qinq(odp_packet_t pkt) { - retflag(pkt, input_flags.vlan_qinq, LAYER_L2); + retflag(pkt, input_flags.vlan_qinq); } int odp_packet_has_arp(odp_packet_t pkt) { - retflag(pkt, input_flags.arp, LAYER_L3); + retflag(pkt, input_flags.arp); } int odp_packet_has_ipv4(odp_packet_t pkt) { - retflag(pkt, input_flags.ipv4, LAYER_L3); + retflag(pkt, input_flags.ipv4); } int odp_packet_has_ipv6(odp_packet_t pkt) { - retflag(pkt, input_flags.ipv6, LAYER_L3); + retflag(pkt, input_flags.ipv6); } int odp_packet_has_ip_bcast(odp_packet_t pkt) { - retflag(pkt, input_flags.ip_bcast, LAYER_L3); + retflag(pkt, input_flags.ip_bcast); } int odp_packet_has_ip_mcast(odp_packet_t pkt) { - retflag(pkt, input_flags.ip_mcast, LAYER_L3); + retflag(pkt, input_flags.ip_mcast); } int odp_packet_has_ipfrag(odp_packet_t pkt) { - retflag(pkt, input_flags.ipfrag, LAYER_L3); + retflag(pkt, input_flags.ipfrag); } int odp_packet_has_ipopt(odp_packet_t pkt) { - retflag(pkt, input_flags.ipopt, LAYER_L3); + retflag(pkt, input_flags.ipopt); } int odp_packet_has_ipsec(odp_packet_t pkt) { - retflag(pkt, input_flags.ipsec, LAYER_L4); + retflag(pkt, input_flags.ipsec); } int odp_packet_has_udp(odp_packet_t pkt) { - retflag(pkt, input_flags.udp, LAYER_L4); + retflag(pkt, input_flags.udp); } int odp_packet_has_tcp(odp_packet_t pkt) { - retflag(pkt, input_flags.tcp, LAYER_L4); + retflag(pkt, input_flags.tcp); } int odp_packet_has_sctp(odp_packet_t pkt) { - retflag(pkt, input_flags.sctp, LAYER_L4); + retflag(pkt, input_flags.sctp); } int odp_packet_has_icmp(odp_packet_t pkt) { - retflag(pkt, input_flags.icmp, LAYER_L4); + retflag(pkt, input_flags.icmp); } odp_packet_color_t odp_packet_color(odp_packet_t pkt) { - retflag(pkt, input_flags.color, LAYER_ALL); + retflag(pkt, input_flags.color); } void odp_packet_color_set(odp_packet_t pkt, odp_packet_color_t color) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - pkt_hdr->p.input_flags.color = color; } @@ -171,29 +157,23 @@ odp_bool_t odp_packet_drop_eligible(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - return !pkt_hdr->p.input_flags.nodrop; } void odp_packet_drop_eligible_set(odp_packet_t pkt, odp_bool_t drop) { - setflag(pkt, input_flags.nodrop, !drop, LAYER_ALL); + setflag(pkt, input_flags.nodrop, !drop); } int8_t odp_packet_shaper_len_adjust(odp_packet_t pkt) { - retflag(pkt, output_flags.shaper_len_adj, LAYER_ALL); + retflag(pkt, output_flags.shaper_len_adj); } void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - pkt_hdr->p.output_flags.shaper_len_adj = adj; } @@ -201,107 +181,107 @@ void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj) void odp_packet_has_l2_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.l2, val, LAYER_L2); + setflag(pkt, input_flags.l2, val); } void odp_packet_has_l3_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.l3, val, LAYER_L3); + setflag(pkt, input_flags.l3, val); } void odp_packet_has_l4_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.l4, val, LAYER_L4); + setflag(pkt, input_flags.l4, val); } void odp_packet_has_eth_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.eth, val, LAYER_L2); + setflag(pkt, input_flags.eth, val); } void odp_packet_has_eth_bcast_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.eth_bcast, val, LAYER_L2); + setflag(pkt, input_flags.eth_bcast, val); } void odp_packet_has_eth_mcast_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.eth_mcast, val, LAYER_L2); + setflag(pkt, input_flags.eth_mcast, val); } void odp_packet_has_jumbo_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.jumbo, val, LAYER_L2); + setflag(pkt, input_flags.jumbo, val); } void odp_packet_has_vlan_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.vlan, val, LAYER_L2); + setflag(pkt, input_flags.vlan, val); } void odp_packet_has_vlan_qinq_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.vlan_qinq, val, LAYER_L2); + setflag(pkt, input_flags.vlan_qinq, val); } void odp_packet_has_arp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.arp, val, LAYER_L3); + setflag(pkt, input_flags.arp, val); } void odp_packet_has_ipv4_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipv4, val, LAYER_L3); + setflag(pkt, input_flags.ipv4, val); } void odp_packet_has_ipv6_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipv6, val, LAYER_L3); + setflag(pkt, input_flags.ipv6, val); } void odp_packet_has_ip_bcast_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ip_bcast, val, LAYER_L3); + setflag(pkt, input_flags.ip_bcast, val); } void odp_packet_has_ip_mcast_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ip_mcast, val, LAYER_L3); + setflag(pkt, input_flags.ip_mcast, val); } void odp_packet_has_ipfrag_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipfrag, val, LAYER_L3); + setflag(pkt, input_flags.ipfrag, val); } void odp_packet_has_ipopt_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipopt, val, LAYER_L3); + setflag(pkt, input_flags.ipopt, val); } void odp_packet_has_ipsec_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipsec, val, LAYER_L4); + setflag(pkt, input_flags.ipsec, val); } void odp_packet_has_udp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.udp, val, LAYER_L4); + setflag(pkt, input_flags.udp, val); } void odp_packet_has_tcp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.tcp, val, LAYER_L4); + setflag(pkt, input_flags.tcp, val); } void odp_packet_has_sctp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.sctp, val, LAYER_L4); + setflag(pkt, input_flags.sctp, val); } void odp_packet_has_icmp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.icmp, val, LAYER_L4); + setflag(pkt, input_flags.icmp, val); } void odp_packet_has_ts_clr(odp_packet_t pkt) diff --git a/platform/linux-dpdk/odp_pool.c b/platform/linux-dpdk/odp_pool.c index e6d415954..0821cdcac 100644 --- a/platform/linux-dpdk/odp_pool.c +++ b/platform/linux-dpdk/odp_pool.c @@ -240,7 +240,8 @@ static int check_params(odp_pool_param_t *params) { odp_pool_capability_t capa; - odp_pool_capability(&capa); + if (odp_pool_capability(&capa) < 0) + return -1; switch (params->type) { case ODP_POOL_BUFFER: @@ -552,6 +553,8 @@ static odp_buffer_t buffer_alloc(pool_entry_t *pool) odp_buffer_t odp_buffer_alloc(odp_pool_t pool_hdl) { + ODP_ASSERT(ODP_POOL_INVALID != pool_hdl); + pool_entry_t *pool = odp_pool_to_entry(pool_hdl); return buffer_alloc(pool); @@ -560,6 +563,9 @@ odp_buffer_t odp_buffer_alloc(odp_pool_t pool_hdl) int odp_buffer_alloc_multi(odp_pool_t pool_hdl, odp_buffer_t buf[], int num) { int i; + + ODP_ASSERT(ODP_POOL_INVALID != pool_hdl); + pool_entry_t *pool = odp_pool_to_entry(pool_hdl); for (i = 0; i < num; i++) { diff --git a/platform/linux-dpdk/odp_time.c b/platform/linux-dpdk/odp_time.c index c1ad973cc..6c066a5b5 100644 --- a/platform/linux-dpdk/odp_time.c +++ b/platform/linux-dpdk/odp_time.c @@ -13,105 +13,182 @@ #include <odp_time_internal.h> #include <rte_cycles.h> #include <string.h> +#include <inttypes.h> + +typedef uint64_t (*time_to_ns_fn) (odp_time_t time); +typedef odp_time_t (*time_cur_fn)(void); +typedef odp_time_t (*time_from_ns_fn) (uint64_t ns); +typedef uint64_t (*time_res_fn)(void); + +typedef struct time_handler_ { + time_to_ns_fn time_to_ns; + time_cur_fn time_cur; + time_from_ns_fn time_from_ns; + time_res_fn time_res; +} time_handler_t; + +typedef struct time_global_t { + struct timespec spec_start; + int use_hw; + uint64_t hw_start; + uint64_t hw_freq_hz; + /* DPDK specific */ + time_handler_t handler; + double tick_per_nsec; + double nsec_per_tick; +} time_global_t; + +static time_global_t global; + +/* + * Posix timespec based functions + */ + +static inline uint64_t time_spec_diff_nsec(struct timespec *t2, + struct timespec *t1) +{ + struct timespec diff; + uint64_t nsec; + + diff.tv_sec = t2->tv_sec - t1->tv_sec; + diff.tv_nsec = t2->tv_nsec - t1->tv_nsec; -typedef union { - odp_time_t ex; - struct timespec in; -} _odp_time_t; + if (diff.tv_nsec < 0) { + diff.tv_nsec += ODP_TIME_SEC_IN_NS; + diff.tv_sec -= 1; + } + + nsec = (diff.tv_sec * ODP_TIME_SEC_IN_NS) + diff.tv_nsec; -static odp_time_t start_time; -static time_handler_t time_handler; -double tick_per_nsec; -double nsec_per_tick; + return nsec; +} -static inline uint64_t time_local_res_dpdk(void) +static inline odp_time_t time_spec_cur(void) { - return rte_get_timer_hz(); + int ret; + odp_time_t time; + struct timespec sys_time; + + ret = clock_gettime(CLOCK_MONOTONIC_RAW, &sys_time); + if (odp_unlikely(ret != 0)) + ODP_ABORT("clock_gettime failed\n"); + + time.nsec = time_spec_diff_nsec(&sys_time, &global.spec_start); + + return time; } -static inline -uint64_t time_to_ns(odp_time_t time) +static inline uint64_t time_spec_res(void) { - uint64_t ns; + int ret; + struct timespec tres; - ns = time.tv_sec * ODP_TIME_SEC_IN_NS; - ns += time.tv_nsec; + ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres); + if (odp_unlikely(ret != 0)) + ODP_ABORT("clock_getres failed\n"); - return ns; + return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec; } -static inline uint64_t time_to_ns_dpdk(odp_time_t time) +static inline uint64_t time_spec_to_ns(odp_time_t time) { - return (time.tv_sec * nsec_per_tick); + return time.nsec; } -static inline odp_time_t time_diff(odp_time_t t2, odp_time_t t1) +static inline odp_time_t time_spec_from_ns(uint64_t ns) { odp_time_t time; - time.tv_sec = t2.tv_sec - t1.tv_sec; - time.tv_nsec = t2.tv_nsec - t1.tv_nsec; - - if (time.tv_nsec < 0) { - time.tv_nsec += ODP_TIME_SEC_IN_NS; - --time.tv_sec; - } + time.nsec = ns; return time; } -static inline odp_time_t time_diff_dpdk(odp_time_t t2, odp_time_t t1) +/* + * HW time counter based functions + */ + +static inline odp_time_t time_hw_cur(void) { odp_time_t time; - time.tv_sec = t2.tv_sec - t1.tv_sec; + time.count = cpu_global_time() - global.hw_start; + return time; } -static inline odp_time_t time_curr(void) +static inline uint64_t time_hw_res(void) { - int ret; - _odp_time_t time; + /* Promise a bit lower resolution than average cycle counter + * frequency */ + return global.hw_freq_hz / 10; +} - ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time.in); - if (odp_unlikely(ret != 0)) - ODP_ABORT("clock_gettime failed\n"); - return time.ex; +static inline uint64_t time_hw_to_ns(odp_time_t time) +{ + uint64_t nsec; + uint64_t freq_hz = global.hw_freq_hz; + uint64_t count = time.count; + uint64_t sec = 0; + + if (count >= freq_hz) { + sec = count / freq_hz; + count = count - sec * freq_hz; + } + + nsec = (ODP_TIME_SEC_IN_NS * count) / freq_hz; + + return (sec * ODP_TIME_SEC_IN_NS) + nsec; } -static inline odp_time_t time_curr_dpdk(void) +static inline odp_time_t time_hw_from_ns(uint64_t ns) { odp_time_t time; + uint64_t count; + uint64_t freq_hz = global.hw_freq_hz; + uint64_t sec = 0; + + if (ns >= ODP_TIME_SEC_IN_NS) { + sec = ns / ODP_TIME_SEC_IN_NS; + ns = ns - sec * ODP_TIME_SEC_IN_NS; + } + + count = sec * freq_hz; + count += (ns * freq_hz) / ODP_TIME_SEC_IN_NS; + + time.count = count; - time.tv_sec = rte_get_timer_cycles(); return time; } -static inline odp_time_t time_local(void) +/* + * Common functions + */ + +static inline odp_time_t time_cur(void) { - odp_time_t time; + if (global.use_hw) + return time_hw_cur(); - time = time_handler.time_curr(); - return time_handler.time_diff(time, start_time); + return time_spec_cur(); } -static inline int time_cmp(odp_time_t t2, odp_time_t t1) +static inline uint64_t time_res(void) { - if (t2.tv_sec < t1.tv_sec) - return -1; - - if (t2.tv_sec > t1.tv_sec) - return 1; + if (global.use_hw) + return time_hw_res(); - return t2.tv_nsec - t1.tv_nsec; + return time_spec_res(); } -static inline int time_cmp_dpdk(odp_time_t t2, odp_time_t t1) +static inline int time_cmp(odp_time_t t2, odp_time_t t1) { - if (t2.tv_sec < t1.tv_sec) - return -1; - if (t2.tv_sec > t1.tv_sec) + if (odp_likely(t2.u64 > t1.u64)) return 1; + + if (t2.u64 < t1.u64) + return -1; + return 0; } @@ -119,61 +196,67 @@ static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2) { odp_time_t time; - time.tv_sec = t2.tv_sec + t1.tv_sec; - time.tv_nsec = t2.tv_nsec + t1.tv_nsec; - - if (time.tv_nsec >= (long)ODP_TIME_SEC_IN_NS) { - time.tv_nsec -= ODP_TIME_SEC_IN_NS; - ++time.tv_sec; - } + time.u64 = t1.u64 + t2.u64; return time; } -static inline odp_time_t time_sum_dpdk(odp_time_t t1, odp_time_t t2) +static inline uint64_t time_to_ns(odp_time_t time) { - odp_time_t time; + if (global.use_hw) + return time_hw_to_ns(time); - time.tv_sec = t2.tv_sec + t1.tv_sec; - return time; + return time_spec_to_ns(time); +} + +static inline odp_time_t time_from_ns(uint64_t ns) +{ + if (global.use_hw) + return time_hw_from_ns(ns); + + return time_spec_from_ns(ns); +} + +static inline uint64_t time_res_dpdk(void) +{ + return rte_get_timer_hz(); } -static inline odp_time_t time_local_from_ns(uint64_t ns) +static inline uint64_t time_to_ns_dpdk(odp_time_t time) +{ + return (time.u64 * global.nsec_per_tick); +} + +static inline odp_time_t time_cur_dpdk(void) { odp_time_t time; - time.tv_sec = ns / ODP_TIME_SEC_IN_NS; - time.tv_nsec = ns - time.tv_sec * ODP_TIME_SEC_IN_NS; + time.u64 = rte_get_timer_cycles() - global.hw_start; return time; } -static inline odp_time_t time_local_from_ns_dpdk(uint64_t ns) +static inline odp_time_t time_from_ns_dpdk(uint64_t ns) { odp_time_t time; - time.tv_sec = ns * tick_per_nsec; + + time.u64 = ns * global.tick_per_nsec; + return time; } +static inline odp_time_t time_local(void) +{ + return global.handler.time_cur(); +} + static inline void time_wait_until(odp_time_t time) { odp_time_t cur; do { cur = time_local(); - } while (time_handler.time_cmp(time, cur) > 0); -} - -static inline uint64_t time_local_res(void) -{ - int ret; - struct timespec tres; - - ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres); - if (odp_unlikely(ret != 0)) - ODP_ABORT("clock_getres failed\n"); - - return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec; + } while (time_cmp(time, cur) > 0); } odp_time_t odp_time_local(void) @@ -188,49 +271,53 @@ odp_time_t odp_time_global(void) odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1) { - return time_handler.time_diff(t2, t1); + odp_time_t time; + + time.u64 = t2.u64 - t1.u64; + + return time; } uint64_t odp_time_to_ns(odp_time_t time) { - return time_handler.time_to_ns(time); + return global.handler.time_to_ns(time); } odp_time_t odp_time_local_from_ns(uint64_t ns) { - return time_handler.time_local_from_ns(ns); + return global.handler.time_from_ns(ns); } odp_time_t odp_time_global_from_ns(uint64_t ns) { - return time_handler.time_local_from_ns(ns); + return global.handler.time_from_ns(ns); } int odp_time_cmp(odp_time_t t2, odp_time_t t1) { - return time_handler.time_cmp(t2, t1); + return time_cmp(t2, t1); } odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2) { - return time_handler.time_sum(t1, t2); + return time_sum(t1, t2); } uint64_t odp_time_local_res(void) { - return time_handler.time_local_res(); + return global.handler.time_res(); } uint64_t odp_time_global_res(void) { - return time_handler.time_local_res(); + return global.handler.time_res(); } void odp_time_wait_ns(uint64_t ns) { odp_time_t cur = time_local(); - odp_time_t wait = time_handler.time_local_from_ns(ns); - odp_time_t end_time = time_handler.time_sum(cur, wait); + odp_time_t wait = global.handler.time_from_ns(ns); + odp_time_t end_time = time_sum(cur, wait); time_wait_until(end_time); } @@ -240,31 +327,6 @@ void odp_time_wait_until(odp_time_t time) return time_wait_until(time); } -static uint64_t time_to_u64(odp_time_t time) -{ - int ret; - struct timespec tres; - uint64_t resolution; - - ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres); - if (odp_unlikely(ret != 0)) - ODP_ABORT("clock_getres failed\n"); - - resolution = (uint64_t)tres.tv_nsec; - - return time_handler.time_to_ns(time) / resolution; -} - -static uint64_t time_to_u64_dpdk(odp_time_t time) -{ - return time.tv_sec; -} - -uint64_t odp_time_to_u64(odp_time_t time) -{ - return time_handler.time_to_u64(time); -} - static odp_bool_t is_invariant_tsc_supported(void) { FILE *file; @@ -311,37 +373,52 @@ static inline odp_bool_t is_dpdk_timer_cycles_support(void) int odp_time_init_global(void) { + int ret = 0; + + memset(&global, 0, sizeof(time_global_t)); + if (is_dpdk_timer_cycles_support()) { - time_handler.time_to_ns = time_to_ns_dpdk; - time_handler.time_diff = time_diff_dpdk; - time_handler.time_curr = time_curr_dpdk; - time_handler.time_cmp = time_cmp_dpdk; - time_handler.time_sum = time_sum_dpdk; - time_handler.time_local_from_ns = time_local_from_ns_dpdk; - time_handler.time_local_res = time_local_res_dpdk; - time_handler.time_to_u64 = time_to_u64_dpdk; - tick_per_nsec = (double)time_local_res_dpdk() / + global.handler.time_to_ns = time_to_ns_dpdk; + global.handler.time_cur = time_cur_dpdk; + global.handler.time_from_ns = time_from_ns_dpdk; + global.handler.time_res = time_res_dpdk; + global.tick_per_nsec = (double)time_res_dpdk() / (double)ODP_TIME_SEC_IN_NS; - nsec_per_tick = (double)ODP_TIME_SEC_IN_NS / - (double)time_local_res_dpdk(); - } else { - time_handler.time_to_ns = time_to_ns; - time_handler.time_diff = time_diff; - time_handler.time_curr = time_curr; - time_handler.time_cmp = time_cmp; - time_handler.time_sum = time_sum; - time_handler.time_local_from_ns = time_local_from_ns; - time_handler.time_local_res = time_local_res; - time_handler.time_to_u64 = time_to_u64; + global.nsec_per_tick = (double)ODP_TIME_SEC_IN_NS / + (double)time_res_dpdk(); + + global.hw_start = rte_get_timer_cycles(); + if (global.hw_start == 0) + return -1; + else + return 0; } - start_time = time_handler.time_curr(); - if (time_handler.time_cmp(start_time, ODP_TIME_NULL) == 0) { - ODP_ABORT("initiate odp time failed\n"); - return -1; - } else { + global.handler.time_to_ns = time_to_ns; + global.handler.time_cur = time_cur; + global.handler.time_from_ns = time_from_ns; + global.handler.time_res = time_res; + + if (cpu_has_global_time()) { + global.use_hw = 1; + global.hw_freq_hz = cpu_global_time_freq(); + + if (global.hw_freq_hz == 0) + return -1; + + printf("HW time counter freq: %" PRIu64 " hz\n\n", + global.hw_freq_hz); + + global.hw_start = cpu_global_time(); return 0; } + + global.spec_start.tv_sec = 0; + global.spec_start.tv_nsec = 0; + + ret = clock_gettime(CLOCK_MONOTONIC_RAW, &global.spec_start); + + return ret; } int odp_time_term_global(void) diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am index 9e8a0064e..8dcdebd29 100644 --- a/platform/linux-generic/Makefile.am +++ b/platform/linux-generic/Makefile.am @@ -9,6 +9,7 @@ AM_CFLAGS += -I$(top_srcdir)/include AM_CFLAGS += -I$(top_srcdir)/include/odp/arch/@ARCH_ABI@ AM_CFLAGS += -I$(top_builddir)/include AM_CFLAGS += -Iinclude +AM_CFLAGS += -D_ODP_PKTIO_IPC include_HEADERS = \ $(top_srcdir)/include/odp.h \ @@ -32,6 +33,7 @@ odpapiinclude_HEADERS = \ $(srcdir)/include/odp/api/cpumask.h \ $(srcdir)/include/odp/api/crypto.h \ $(srcdir)/include/odp/api/debug.h \ + $(srcdir)/include/odp/api/deprecated.h \ $(srcdir)/include/odp/api/errno.h \ $(srcdir)/include/odp/api/event.h \ $(srcdir)/include/odp/api/hash.h \ @@ -145,6 +147,7 @@ noinst_HEADERS = \ ${srcdir}/include/odp_schedule_if.h \ ${srcdir}/include/odp_sorted_list_internal.h \ ${srcdir}/include/odp_shm_internal.h \ + ${srcdir}/include/odp_time_internal.h \ ${srcdir}/include/odp_timer_internal.h \ ${srcdir}/include/odp_timer_wheel_internal.h \ ${srcdir}/include/odp_traffic_mngr_internal.h \ @@ -218,6 +221,12 @@ __LIB__libodp_linux_la_SOURCES = \ arch/@ARCH_DIR@/odp_cpu_arch.c \ arch/@ARCH_DIR@/odp_sysinfo_parse.c +__LIB__libodp_linux_la_LIBADD = $(ATOMIC_LIBS) + +if ARCH_IS_X86 +__LIB__libodp_linux_la_SOURCES += arch/@ARCH_DIR@/cpu_flags.c +endif + if HAVE_PCAP __LIB__libodp_linux_la_SOURCES += pktio/pcap.c endif @@ -225,9 +234,9 @@ endif # Create symlink for ABI header files. Application does not need to use the arch # specific include path for installed files. install-data-hook: - if [ -h $(prefix)/include/odp/api/abi ]; then \ - : \ + if [ -h $(DESTDIR)$(prefix)/include/odp/api/abi ]; then \ + : ; \ else \ - $(LN_S) -rf $(prefix)/include/odp/arch/@ARCH_ABI@/odp/api/abi \ - $(prefix)/include/odp/api/abi; \ + $(LN_S) -rf $(DESTDIR)$(prefix)/include/odp/arch/@ARCH_ABI@/odp/api/abi \ + $(DESTDIR)$(prefix)/include/odp/api/abi; \ fi diff --git a/platform/linux-generic/arch/arm/odp_cpu_arch.c b/platform/linux-generic/arch/arm/odp_cpu_arch.c index 2ac223e07..c31f90844 100644 --- a/platform/linux-generic/arch/arm/odp_cpu_arch.c +++ b/platform/linux-generic/arch/arm/odp_cpu_arch.c @@ -13,6 +13,7 @@ #include <odp/api/hints.h> #include <odp/api/system_info.h> #include <odp_debug_internal.h> +#include <odp_time_internal.h> #define GIGA 1000000000 @@ -46,3 +47,18 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +int cpu_has_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time_freq(void) +{ + return 0; +} diff --git a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c b/platform/linux-generic/arch/arm/odp_sysinfo_parse.c index 53e2aaeaf..8ae2022ac 100644 --- a/platform/linux-generic/arch/arm/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/arm/odp_sysinfo_parse.c @@ -25,3 +25,7 @@ uint64_t odp_cpu_hz_current(int id ODP_UNUSED) { return 0; } + +void sys_info_print_arch(void) +{ +} diff --git a/platform/linux-generic/arch/default/odp_cpu_arch.c b/platform/linux-generic/arch/default/odp_cpu_arch.c index 2ac223e07..c31f90844 100644 --- a/platform/linux-generic/arch/default/odp_cpu_arch.c +++ b/platform/linux-generic/arch/default/odp_cpu_arch.c @@ -13,6 +13,7 @@ #include <odp/api/hints.h> #include <odp/api/system_info.h> #include <odp_debug_internal.h> +#include <odp_time_internal.h> #define GIGA 1000000000 @@ -46,3 +47,18 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +int cpu_has_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time_freq(void) +{ + return 0; +} diff --git a/platform/linux-generic/arch/default/odp_sysinfo_parse.c b/platform/linux-generic/arch/default/odp_sysinfo_parse.c index 53e2aaeaf..8ae2022ac 100644 --- a/platform/linux-generic/arch/default/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/default/odp_sysinfo_parse.c @@ -25,3 +25,7 @@ uint64_t odp_cpu_hz_current(int id ODP_UNUSED) { return 0; } + +void sys_info_print_arch(void) +{ +} diff --git a/platform/linux-generic/arch/mips64/odp_cpu_arch.c b/platform/linux-generic/arch/mips64/odp_cpu_arch.c index 646acf9c1..f7eafa0fb 100644 --- a/platform/linux-generic/arch/mips64/odp_cpu_arch.c +++ b/platform/linux-generic/arch/mips64/odp_cpu_arch.c @@ -7,6 +7,7 @@ #include <odp/api/cpu.h> #include <odp/api/hints.h> #include <odp/api/system_info.h> +#include <odp_time_internal.h> uint64_t odp_cpu_cycles(void) { @@ -29,3 +30,18 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +int cpu_has_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time_freq(void) +{ + return 0; +} diff --git a/platform/linux-generic/arch/mips64/odp_sysinfo_parse.c b/platform/linux-generic/arch/mips64/odp_sysinfo_parse.c index 407264b7f..d6f75f283 100644 --- a/platform/linux-generic/arch/mips64/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/mips64/odp_sysinfo_parse.c @@ -62,3 +62,7 @@ uint64_t odp_cpu_hz_current(int id ODP_UNUSED) { return 0; } + +void sys_info_print_arch(void) +{ +} diff --git a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c index 2ac223e07..c31f90844 100644 --- a/platform/linux-generic/arch/powerpc/odp_cpu_arch.c +++ b/platform/linux-generic/arch/powerpc/odp_cpu_arch.c @@ -13,6 +13,7 @@ #include <odp/api/hints.h> #include <odp/api/system_info.h> #include <odp_debug_internal.h> +#include <odp_time_internal.h> #define GIGA 1000000000 @@ -46,3 +47,18 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +int cpu_has_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time(void) +{ + return 0; +} + +uint64_t cpu_global_time_freq(void) +{ + return 0; +} diff --git a/platform/linux-generic/arch/powerpc/odp_sysinfo_parse.c b/platform/linux-generic/arch/powerpc/odp_sysinfo_parse.c index 3b88d55b6..bd4b9b429 100644 --- a/platform/linux-generic/arch/powerpc/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/powerpc/odp_sysinfo_parse.c @@ -61,3 +61,7 @@ uint64_t odp_cpu_hz_current(int id ODP_UNUSED) { return 0; } + +void sys_info_print_arch(void) +{ +} diff --git a/platform/linux-generic/arch/x86/cpu_flags.c b/platform/linux-generic/arch/x86/cpu_flags.c new file mode 100644 index 000000000..a492a35bf --- /dev/null +++ b/platform/linux-generic/arch/x86/cpu_flags.c @@ -0,0 +1,368 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch/x86/cpu_flags.h> +#include <odp_debug_internal.h> +#include <odp_time_internal.h> +#include <stdio.h> +#include <stdint.h> + +enum rte_cpu_flag_t { + /* (EAX 01h) ECX features*/ + RTE_CPUFLAG_SSE3 = 0, /**< SSE3 */ + RTE_CPUFLAG_PCLMULQDQ, /**< PCLMULQDQ */ + RTE_CPUFLAG_DTES64, /**< DTES64 */ + RTE_CPUFLAG_MONITOR, /**< MONITOR */ + RTE_CPUFLAG_DS_CPL, /**< DS_CPL */ + RTE_CPUFLAG_VMX, /**< VMX */ + RTE_CPUFLAG_SMX, /**< SMX */ + RTE_CPUFLAG_EIST, /**< EIST */ + RTE_CPUFLAG_TM2, /**< TM2 */ + RTE_CPUFLAG_SSSE3, /**< SSSE3 */ + RTE_CPUFLAG_CNXT_ID, /**< CNXT_ID */ + RTE_CPUFLAG_FMA, /**< FMA */ + RTE_CPUFLAG_CMPXCHG16B, /**< CMPXCHG16B */ + RTE_CPUFLAG_XTPR, /**< XTPR */ + RTE_CPUFLAG_PDCM, /**< PDCM */ + RTE_CPUFLAG_PCID, /**< PCID */ + RTE_CPUFLAG_DCA, /**< DCA */ + RTE_CPUFLAG_SSE4_1, /**< SSE4_1 */ + RTE_CPUFLAG_SSE4_2, /**< SSE4_2 */ + RTE_CPUFLAG_X2APIC, /**< X2APIC */ + RTE_CPUFLAG_MOVBE, /**< MOVBE */ + RTE_CPUFLAG_POPCNT, /**< POPCNT */ + RTE_CPUFLAG_TSC_DEADLINE, /**< TSC_DEADLINE */ + RTE_CPUFLAG_AES, /**< AES */ + RTE_CPUFLAG_XSAVE, /**< XSAVE */ + RTE_CPUFLAG_OSXSAVE, /**< OSXSAVE */ + RTE_CPUFLAG_AVX, /**< AVX */ + RTE_CPUFLAG_F16C, /**< F16C */ + RTE_CPUFLAG_RDRAND, /**< RDRAND */ + + /* (EAX 01h) EDX features */ + RTE_CPUFLAG_FPU, /**< FPU */ + RTE_CPUFLAG_VME, /**< VME */ + RTE_CPUFLAG_DE, /**< DE */ + RTE_CPUFLAG_PSE, /**< PSE */ + RTE_CPUFLAG_TSC, /**< TSC */ + RTE_CPUFLAG_MSR, /**< MSR */ + RTE_CPUFLAG_PAE, /**< PAE */ + RTE_CPUFLAG_MCE, /**< MCE */ + RTE_CPUFLAG_CX8, /**< CX8 */ + RTE_CPUFLAG_APIC, /**< APIC */ + RTE_CPUFLAG_SEP, /**< SEP */ + RTE_CPUFLAG_MTRR, /**< MTRR */ + RTE_CPUFLAG_PGE, /**< PGE */ + RTE_CPUFLAG_MCA, /**< MCA */ + RTE_CPUFLAG_CMOV, /**< CMOV */ + RTE_CPUFLAG_PAT, /**< PAT */ + RTE_CPUFLAG_PSE36, /**< PSE36 */ + RTE_CPUFLAG_PSN, /**< PSN */ + RTE_CPUFLAG_CLFSH, /**< CLFSH */ + RTE_CPUFLAG_DS, /**< DS */ + RTE_CPUFLAG_ACPI, /**< ACPI */ + RTE_CPUFLAG_MMX, /**< MMX */ + RTE_CPUFLAG_FXSR, /**< FXSR */ + RTE_CPUFLAG_SSE, /**< SSE */ + RTE_CPUFLAG_SSE2, /**< SSE2 */ + RTE_CPUFLAG_SS, /**< SS */ + RTE_CPUFLAG_HTT, /**< HTT */ + RTE_CPUFLAG_TM, /**< TM */ + RTE_CPUFLAG_PBE, /**< PBE */ + + /* (EAX 06h) EAX features */ + RTE_CPUFLAG_DIGTEMP, /**< DIGTEMP */ + RTE_CPUFLAG_TRBOBST, /**< TRBOBST */ + RTE_CPUFLAG_ARAT, /**< ARAT */ + RTE_CPUFLAG_PLN, /**< PLN */ + RTE_CPUFLAG_ECMD, /**< ECMD */ + RTE_CPUFLAG_PTM, /**< PTM */ + + /* (EAX 06h) ECX features */ + RTE_CPUFLAG_MPERF_APERF_MSR, /**< MPERF_APERF_MSR */ + RTE_CPUFLAG_ACNT2, /**< ACNT2 */ + RTE_CPUFLAG_ENERGY_EFF, /**< ENERGY_EFF */ + + /* (EAX 07h, ECX 0h) EBX features */ + RTE_CPUFLAG_FSGSBASE, /**< FSGSBASE */ + RTE_CPUFLAG_BMI1, /**< BMI1 */ + RTE_CPUFLAG_HLE, /**< Hardware Lock elision */ + RTE_CPUFLAG_AVX2, /**< AVX2 */ + RTE_CPUFLAG_SMEP, /**< SMEP */ + RTE_CPUFLAG_BMI2, /**< BMI2 */ + RTE_CPUFLAG_ERMS, /**< ERMS */ + RTE_CPUFLAG_INVPCID, /**< INVPCID */ + RTE_CPUFLAG_RTM, /**< Transactional memory */ + RTE_CPUFLAG_AVX512F, /**< AVX512F */ + + /* (EAX 80000001h) ECX features */ + RTE_CPUFLAG_LAHF_SAHF, /**< LAHF_SAHF */ + RTE_CPUFLAG_LZCNT, /**< LZCNT */ + + /* (EAX 80000001h) EDX features */ + RTE_CPUFLAG_SYSCALL, /**< SYSCALL */ + RTE_CPUFLAG_XD, /**< XD */ + RTE_CPUFLAG_1GB_PG, /**< 1GB_PG */ + RTE_CPUFLAG_RDTSCP, /**< RDTSCP */ + RTE_CPUFLAG_EM64T, /**< EM64T */ + + /* (EAX 80000007h) EDX features */ + RTE_CPUFLAG_INVTSC, /**< INVTSC */ + + /* The last item */ + RTE_CPUFLAG_NUMFLAGS, /**< This should always be the last! */ +}; + +enum cpu_register_t { + RTE_REG_EAX = 0, + RTE_REG_EBX, + RTE_REG_ECX, + RTE_REG_EDX, +}; + +typedef uint32_t cpuid_registers_t[4]; + +/** + * Struct to hold a processor feature entry + */ +struct feature_entry { + uint32_t leaf; /**< cpuid leaf */ + uint32_t subleaf; /**< cpuid subleaf */ + uint32_t reg; /**< cpuid register */ + uint32_t bit; /**< cpuid register bit */ +#define CPU_FLAG_NAME_MAX_LEN 64 + char name[CPU_FLAG_NAME_MAX_LEN]; /**< String for printing */ +}; + +#define FEAT_DEF(name, leaf, subleaf, reg, bit) \ + [RTE_CPUFLAG_##name] = {leaf, subleaf, reg, bit, #name }, + +static const struct feature_entry cpu_feature_table[] = { + FEAT_DEF(SSE3, 0x00000001, 0, RTE_REG_ECX, 0) + FEAT_DEF(PCLMULQDQ, 0x00000001, 0, RTE_REG_ECX, 1) + FEAT_DEF(DTES64, 0x00000001, 0, RTE_REG_ECX, 2) + FEAT_DEF(MONITOR, 0x00000001, 0, RTE_REG_ECX, 3) + FEAT_DEF(DS_CPL, 0x00000001, 0, RTE_REG_ECX, 4) + FEAT_DEF(VMX, 0x00000001, 0, RTE_REG_ECX, 5) + FEAT_DEF(SMX, 0x00000001, 0, RTE_REG_ECX, 6) + FEAT_DEF(EIST, 0x00000001, 0, RTE_REG_ECX, 7) + FEAT_DEF(TM2, 0x00000001, 0, RTE_REG_ECX, 8) + FEAT_DEF(SSSE3, 0x00000001, 0, RTE_REG_ECX, 9) + FEAT_DEF(CNXT_ID, 0x00000001, 0, RTE_REG_ECX, 10) + FEAT_DEF(FMA, 0x00000001, 0, RTE_REG_ECX, 12) + FEAT_DEF(CMPXCHG16B, 0x00000001, 0, RTE_REG_ECX, 13) + FEAT_DEF(XTPR, 0x00000001, 0, RTE_REG_ECX, 14) + FEAT_DEF(PDCM, 0x00000001, 0, RTE_REG_ECX, 15) + FEAT_DEF(PCID, 0x00000001, 0, RTE_REG_ECX, 17) + FEAT_DEF(DCA, 0x00000001, 0, RTE_REG_ECX, 18) + FEAT_DEF(SSE4_1, 0x00000001, 0, RTE_REG_ECX, 19) + FEAT_DEF(SSE4_2, 0x00000001, 0, RTE_REG_ECX, 20) + FEAT_DEF(X2APIC, 0x00000001, 0, RTE_REG_ECX, 21) + FEAT_DEF(MOVBE, 0x00000001, 0, RTE_REG_ECX, 22) + FEAT_DEF(POPCNT, 0x00000001, 0, RTE_REG_ECX, 23) + FEAT_DEF(TSC_DEADLINE, 0x00000001, 0, RTE_REG_ECX, 24) + FEAT_DEF(AES, 0x00000001, 0, RTE_REG_ECX, 25) + FEAT_DEF(XSAVE, 0x00000001, 0, RTE_REG_ECX, 26) + FEAT_DEF(OSXSAVE, 0x00000001, 0, RTE_REG_ECX, 27) + FEAT_DEF(AVX, 0x00000001, 0, RTE_REG_ECX, 28) + FEAT_DEF(F16C, 0x00000001, 0, RTE_REG_ECX, 29) + FEAT_DEF(RDRAND, 0x00000001, 0, RTE_REG_ECX, 30) + + FEAT_DEF(FPU, 0x00000001, 0, RTE_REG_EDX, 0) + FEAT_DEF(VME, 0x00000001, 0, RTE_REG_EDX, 1) + FEAT_DEF(DE, 0x00000001, 0, RTE_REG_EDX, 2) + FEAT_DEF(PSE, 0x00000001, 0, RTE_REG_EDX, 3) + FEAT_DEF(TSC, 0x00000001, 0, RTE_REG_EDX, 4) + FEAT_DEF(MSR, 0x00000001, 0, RTE_REG_EDX, 5) + FEAT_DEF(PAE, 0x00000001, 0, RTE_REG_EDX, 6) + FEAT_DEF(MCE, 0x00000001, 0, RTE_REG_EDX, 7) + FEAT_DEF(CX8, 0x00000001, 0, RTE_REG_EDX, 8) + FEAT_DEF(APIC, 0x00000001, 0, RTE_REG_EDX, 9) + FEAT_DEF(SEP, 0x00000001, 0, RTE_REG_EDX, 11) + FEAT_DEF(MTRR, 0x00000001, 0, RTE_REG_EDX, 12) + FEAT_DEF(PGE, 0x00000001, 0, RTE_REG_EDX, 13) + FEAT_DEF(MCA, 0x00000001, 0, RTE_REG_EDX, 14) + FEAT_DEF(CMOV, 0x00000001, 0, RTE_REG_EDX, 15) + FEAT_DEF(PAT, 0x00000001, 0, RTE_REG_EDX, 16) + FEAT_DEF(PSE36, 0x00000001, 0, RTE_REG_EDX, 17) + FEAT_DEF(PSN, 0x00000001, 0, RTE_REG_EDX, 18) + FEAT_DEF(CLFSH, 0x00000001, 0, RTE_REG_EDX, 19) + FEAT_DEF(DS, 0x00000001, 0, RTE_REG_EDX, 21) + FEAT_DEF(ACPI, 0x00000001, 0, RTE_REG_EDX, 22) + FEAT_DEF(MMX, 0x00000001, 0, RTE_REG_EDX, 23) + FEAT_DEF(FXSR, 0x00000001, 0, RTE_REG_EDX, 24) + FEAT_DEF(SSE, 0x00000001, 0, RTE_REG_EDX, 25) + FEAT_DEF(SSE2, 0x00000001, 0, RTE_REG_EDX, 26) + FEAT_DEF(SS, 0x00000001, 0, RTE_REG_EDX, 27) + FEAT_DEF(HTT, 0x00000001, 0, RTE_REG_EDX, 28) + FEAT_DEF(TM, 0x00000001, 0, RTE_REG_EDX, 29) + FEAT_DEF(PBE, 0x00000001, 0, RTE_REG_EDX, 31) + + FEAT_DEF(DIGTEMP, 0x00000006, 0, RTE_REG_EAX, 0) + FEAT_DEF(TRBOBST, 0x00000006, 0, RTE_REG_EAX, 1) + FEAT_DEF(ARAT, 0x00000006, 0, RTE_REG_EAX, 2) + FEAT_DEF(PLN, 0x00000006, 0, RTE_REG_EAX, 4) + FEAT_DEF(ECMD, 0x00000006, 0, RTE_REG_EAX, 5) + FEAT_DEF(PTM, 0x00000006, 0, RTE_REG_EAX, 6) + + FEAT_DEF(MPERF_APERF_MSR, 0x00000006, 0, RTE_REG_ECX, 0) + FEAT_DEF(ACNT2, 0x00000006, 0, RTE_REG_ECX, 1) + FEAT_DEF(ENERGY_EFF, 0x00000006, 0, RTE_REG_ECX, 3) + + FEAT_DEF(FSGSBASE, 0x00000007, 0, RTE_REG_EBX, 0) + FEAT_DEF(BMI1, 0x00000007, 0, RTE_REG_EBX, 2) + FEAT_DEF(HLE, 0x00000007, 0, RTE_REG_EBX, 4) + FEAT_DEF(AVX2, 0x00000007, 0, RTE_REG_EBX, 5) + FEAT_DEF(SMEP, 0x00000007, 0, RTE_REG_EBX, 6) + FEAT_DEF(BMI2, 0x00000007, 0, RTE_REG_EBX, 7) + FEAT_DEF(ERMS, 0x00000007, 0, RTE_REG_EBX, 8) + FEAT_DEF(INVPCID, 0x00000007, 0, RTE_REG_EBX, 10) + FEAT_DEF(RTM, 0x00000007, 0, RTE_REG_EBX, 11) + FEAT_DEF(AVX512F, 0x00000007, 0, RTE_REG_EBX, 16) + + FEAT_DEF(LAHF_SAHF, 0x80000001, 0, RTE_REG_ECX, 0) + FEAT_DEF(LZCNT, 0x80000001, 0, RTE_REG_ECX, 4) + + FEAT_DEF(SYSCALL, 0x80000001, 0, RTE_REG_EDX, 11) + FEAT_DEF(XD, 0x80000001, 0, RTE_REG_EDX, 20) + FEAT_DEF(1GB_PG, 0x80000001, 0, RTE_REG_EDX, 26) + FEAT_DEF(RDTSCP, 0x80000001, 0, RTE_REG_EDX, 27) + FEAT_DEF(EM64T, 0x80000001, 0, RTE_REG_EDX, 29) + + FEAT_DEF(INVTSC, 0x80000007, 0, RTE_REG_EDX, 8) +}; + +/* + * Execute CPUID instruction and get contents of a specific register + * + * This function, when compiled with GCC, will generate architecture-neutral + * code, as per GCC manual. + */ +static void cpu_get_features(uint32_t leaf, uint32_t subleaf, + cpuid_registers_t out) +{ +#if defined(__i386__) && defined(__PIC__) + /* %ebx is a forbidden register if we compile with -fPIC or -fPIE */ + __asm__ __volatile__("movl %%ebx,%0 ; cpuid ; xchgl %%ebx,%0" + : "=r" (out[RTE_REG_EBX]), + "=a" (out[RTE_REG_EAX]), + "=c" (out[RTE_REG_ECX]), + "=d" (out[RTE_REG_EDX]) + : "a" (leaf), "c" (subleaf)); +#else + __asm__ __volatile__("cpuid" + : "=a" (out[RTE_REG_EAX]), + "=b" (out[RTE_REG_EBX]), + "=c" (out[RTE_REG_ECX]), + "=d" (out[RTE_REG_EDX]) + : "a" (leaf), "c" (subleaf)); +#endif +} + +static int cpu_get_flag_enabled(enum rte_cpu_flag_t feature) +{ + const struct feature_entry *feat; + cpuid_registers_t regs; + + if (feature >= RTE_CPUFLAG_NUMFLAGS) + /* Flag does not match anything in the feature tables */ + return -1; + + feat = &cpu_feature_table[feature]; + + if (!feat->leaf) + /* This entry in the table wasn't filled out! */ + return -1; + + cpu_get_features(feat->leaf & 0xffff0000, 0, regs); + if (((regs[RTE_REG_EAX] ^ feat->leaf) & 0xffff0000) || + regs[RTE_REG_EAX] < feat->leaf) + return 0; + + /* get the cpuid leaf containing the desired feature */ + cpu_get_features(feat->leaf, feat->subleaf, regs); + + /* check if the feature is enabled */ + return (regs[feat->reg] >> feat->bit) & 1; +} + +static const char *cpu_get_flag_name(enum rte_cpu_flag_t feature) +{ + if (feature >= RTE_CPUFLAG_NUMFLAGS) + return NULL; + return cpu_feature_table[feature].name; +} + +void cpu_flags_print_all(void) +{ + int len, i; + int max_str = 1024; + int max_len = max_str - 1; + char str[max_str]; + + len = snprintf(str, max_len, "\nCPU features supported:\n"); + + for (i = 0; i < RTE_CPUFLAG_NUMFLAGS; i++) { + if (cpu_get_flag_enabled(i) > 0) + len += snprintf(&str[len], max_len - len, "%s ", + cpu_get_flag_name(i)); + } + + len += snprintf(&str[len], max_len - len, + "\n\nCPU features NOT supported:\n"); + + for (i = 0; i < RTE_CPUFLAG_NUMFLAGS; i++) { + if (cpu_get_flag_enabled(i) <= 0) + len += snprintf(&str[len], max_len - len, "%s ", + cpu_get_flag_name(i)); + } + + len += snprintf(&str[len], max_len - len, "\n\n"); + + str[len] = '\0'; + ODP_PRINT("%s", str); +} + +int cpu_has_global_time(void) +{ + if (cpu_get_flag_enabled(RTE_CPUFLAG_INVTSC) > 0) + return 1; + + return 0; +} diff --git a/platform/linux-generic/arch/x86/cpu_flags.h b/platform/linux-generic/arch/x86/cpu_flags.h new file mode 100644 index 000000000..f709ca08b --- /dev/null +++ b/platform/linux-generic/arch/x86/cpu_flags.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_PLAT_CPU_FLAGS_H_ +#define ODP_PLAT_CPU_FLAGS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void cpu_flags_print_all(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/arch/x86/odp_cpu_arch.c b/platform/linux-generic/arch/x86/odp_cpu_arch.c index c8cf27b65..b1da428b9 100644 --- a/platform/linux-generic/arch/x86/odp_cpu_arch.c +++ b/platform/linux-generic/arch/x86/odp_cpu_arch.c @@ -3,7 +3,14 @@ * * SPDX-License-Identifier: BSD-3-Clause */ + +#include <odp_posix_extensions.h> + #include <odp/api/cpu.h> +#include <odp_time_internal.h> +#include <odp_debug_internal.h> + +#include <time.h> uint64_t odp_cpu_cycles(void) { @@ -31,3 +38,64 @@ uint64_t odp_cpu_cycles_resolution(void) { return 1; } + +uint64_t cpu_global_time(void) +{ + return odp_cpu_cycles(); +} + +#define SEC_IN_NS 1000000000ULL + +/* Measure TSC frequency. Frequency information registers are defined for x86, + * but those are often not enumerated. */ +uint64_t cpu_global_time_freq(void) +{ + struct timespec sleep, ts1, ts2; + uint64_t t1, t2, ts_nsec, cycles, hz; + int i; + uint64_t avg = 0; + int rounds = 3; + int warm_up = 1; + + for (i = 0; i < rounds; i++) { + sleep.tv_sec = 0; + + if (warm_up) + sleep.tv_nsec = SEC_IN_NS / 1000; + else + sleep.tv_nsec = SEC_IN_NS / 4; + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts1)) { + ODP_DBG("clock_gettime failed\n"); + return 0; + } + + t1 = cpu_global_time(); + + if (nanosleep(&sleep, NULL) < 0) { + ODP_DBG("nanosleep failed\n"); + return 0; + } + + if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts2)) { + ODP_DBG("clock_gettime failed\n"); + return 0; + } + + t2 = cpu_global_time(); + + ts_nsec = (ts2.tv_sec - ts1.tv_sec) * SEC_IN_NS; + ts_nsec += ts2.tv_nsec - ts1.tv_nsec; + + cycles = t2 - t1; + + hz = (cycles * SEC_IN_NS) / ts_nsec; + + if (warm_up) + warm_up = 0; + else + avg += hz; + } + + return avg / (rounds - 1); +} diff --git a/platform/linux-generic/arch/x86/odp_sysinfo_parse.c b/platform/linux-generic/arch/x86/odp_sysinfo_parse.c index 96127ec67..d77165a41 100644 --- a/platform/linux-generic/arch/x86/odp_sysinfo_parse.c +++ b/platform/linux-generic/arch/x86/odp_sysinfo_parse.c @@ -5,6 +5,7 @@ */ #include <odp_internal.h> +#include <arch/x86/cpu_flags.h> #include <string.h> int cpuinfo_parser(FILE *file, system_info_t *sysinfo) @@ -73,3 +74,8 @@ uint64_t odp_cpu_hz_current(int id) return 0; } + +void sys_info_print_arch(void) +{ + cpu_flags_print_all(); +} diff --git a/platform/linux-generic/include/odp/api/debug.h b/platform/linux-generic/include/odp/api/debug.h index 7db143395..bef2fd0eb 100644 --- a/platform/linux-generic/include/odp/api/debug.h +++ b/platform/linux-generic/include/odp/api/debug.h @@ -19,17 +19,44 @@ extern "C" { #include <odp/api/spec/debug.h> -#if defined(__GNUC__) && !defined(__clang__) - -#if __GNUC__ < 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ < 6)) - /** - * @internal _Static_assert was only added in GCC 4.6. Provide a weak replacement - * for previous versions. + * @internal _Static_assert was only added in GCC 4.6 and the C++ version + * static_assert for g++ 6 and above. Provide a weak replacement for previous + * versions. */ -#define _Static_assert(e, s) (extern int (*static_assert_checker(void)) \ - [sizeof(struct { unsigned int error_if_negative:(e) ? 1 : -1; })]) +#define _odp_merge(a, b) a##b +/** @internal */ +#define _odp_label(a) _odp_merge(_ODP_SASSERT_, a) +/** @internal */ +#define _ODP_SASSERT _odp_label(__COUNTER__) +/** @internal */ +#define _ODP_SASSERT_ENUM(e) { _ODP_SASSERT = 1 / !!(e) } +/** @internal */ +#define _odp_static_assert(e, s) enum _ODP_SASSERT_ENUM(e) + +#if defined(__clang__) +#if defined(__cplusplus) +#if !__has_feature(cxx_static_assert) && !defined(static_assert) +/** @internal */ +#define static_assert(e, s) _odp_static_assert(e, s) +#endif +#elif !__has_feature(c_static_assert) && !defined(_Static_assert) +/** @internal */ +#define _Static_assert(e, s) _odp_static_assert(e, s) +#endif +#elif defined(__GNUC__) +#if __GNUC__ < 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ < 6)) || \ + (__GNUC__ < 6 && defined(__cplusplus)) +#if defined(__cplusplus) +#if !defined(static_assert) +/** @intenral */ +#define static_assert(e, s) _odp_static_assert(e, s) +#endif +#elif !defined(_Static_assert) +/** @internal */ +#define _Static_assert(e, s) _odp_static_assert(e, s) +#endif #endif #endif @@ -39,9 +66,11 @@ extern "C" { * if condition 'cond' is false. Macro definition is empty when compiler is not * supported or the compiler does not support static assertion. */ -#define ODP_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg) +#ifndef __cplusplus +#define ODP_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg) -#ifdef __cplusplus +#else +#define ODP_STATIC_ASSERT(cond, msg) static_assert(cond, msg) } #endif diff --git a/platform/linux-generic/include/odp/api/deprecated.h b/platform/linux-generic/include/odp/api/deprecated.h new file mode 100644 index 000000000..82797ebc4 --- /dev/null +++ b/platform/linux-generic/include/odp/api/deprecated.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file + * + * Control deprecated API definitions + */ + +#ifndef ODP_PLAT_DEPRECATED_H_ +#define ODP_PLAT_DEPRECATED_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <odp/api/spec/deprecated.h> + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/include/odp/api/plat/packet_types.h b/platform/linux-generic/include/odp/api/plat/packet_types.h index 7e3c51e6c..a209c759f 100644 --- a/platform/linux-generic/include/odp/api/plat/packet_types.h +++ b/platform/linux-generic/include/odp/api/plat/packet_types.h @@ -105,8 +105,8 @@ typedef union { /** All input flags */ uint64_t all; + /** Individual input flags */ struct { - uint64_t parsed_l2:1; /**< L2 parsed */ uint64_t dst_queue:1; /**< Dst queue present */ uint64_t flow_hash:1; /**< Flow hash present */ diff --git a/platform/linux-generic/include/odp/api/plat/time_types.h b/platform/linux-generic/include/odp/api/plat/time_types.h index 4847f3b1f..e7111c8c5 100644 --- a/platform/linux-generic/include/odp/api/plat/time_types.h +++ b/platform/linux-generic/include/odp/api/plat/time_types.h @@ -22,15 +22,25 @@ extern "C" { **/ /** - * @internal Time structure used to isolate odp-linux implementation from - * the linux timespec structure, which is dependent on POSIX extension level. + * @internal Time structure used for both POSIX timespec and HW counter + * implementations. */ typedef struct odp_time_t { - int64_t tv_sec; /**< @internal Seconds */ - int64_t tv_nsec; /**< @internal Nanoseconds */ + /** @internal Variant mappings for time type */ + union { + /** @internal Used with generic 64 bit operations */ + uint64_t u64; + + /** @internal Nanoseconds */ + uint64_t nsec; + + /** @internal HW timer counter value */ + uint64_t count; + + }; } odp_time_t; -#define ODP_TIME_NULL ((odp_time_t){0, 0}) +#define ODP_TIME_NULL ((odp_time_t){.u64 = 0}) /** * @} diff --git a/platform/linux-generic/include/odp/api/plat/traffic_mngr_types.h b/platform/linux-generic/include/odp/api/plat/traffic_mngr_types.h index b766afecd..f47a13f6f 100644 --- a/platform/linux-generic/include/odp/api/plat/traffic_mngr_types.h +++ b/platform/linux-generic/include/odp/api/plat/traffic_mngr_types.h @@ -168,7 +168,7 @@ typedef odp_tm_handle_t odp_tm_wred_t; */ #define ODP_TM_ROOT ((odp_tm_handle_t)-1) -/** Get printable format of odp_queue_t */ +/** @internal Get printable format of odp_tm_handle_t @param hdl @return */ static inline uint64_t odp_tm_handle_to_u64(odp_tm_handle_t hdl) { return hdl; diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h index f85b76eaa..c3b70b231 100644 --- a/platform/linux-generic/include/odp_crypto_internal.h +++ b/platform/linux-generic/include/odp_crypto_internal.h @@ -11,8 +11,6 @@ extern "C" { #endif -#include <openssl/des.h> -#include <openssl/aes.h> #include <openssl/evp.h> #define MAX_IV_LEN 64 @@ -42,34 +40,17 @@ struct odp_crypto_generic_session { struct { /* Copy of session IV data */ uint8_t iv_data[MAX_IV_LEN]; + uint8_t key_data[EVP_MAX_KEY_LENGTH]; - union { - struct { - DES_key_schedule ks1; - DES_key_schedule ks2; - DES_key_schedule ks3; - } des; - struct { - AES_KEY key; - } aes; - struct { - EVP_CIPHER_CTX *ctx; - } aes_gcm; - } data; + const EVP_CIPHER *evp_cipher; crypto_func_t func; } cipher; struct { - union { - struct { - uint8_t key[16]; - uint32_t bytes; - } md5; - struct { - uint8_t key[32]; - uint32_t bytes; - } sha256; - } data; + uint8_t key[EVP_MAX_KEY_LENGTH]; + uint32_t key_length; + uint32_t bytes; + const EVP_MD *evp_md; crypto_func_t func; } auth; }; diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h index e1267cff7..8bae028d9 100644 --- a/platform/linux-generic/include/odp_internal.h +++ b/platform/linux-generic/include/odp_internal.h @@ -128,6 +128,7 @@ int _odp_ishm_term_local(void); int cpuinfo_parser(FILE *file, system_info_t *sysinfo); uint64_t odp_cpu_hz_current(int id); +void sys_info_print_arch(void); #ifdef __cplusplus } diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 0a9f17799..a480a7484 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -80,18 +80,6 @@ ODP_STATIC_ASSERT(sizeof(output_flags_t) == sizeof(uint32_t), "OUTPUT_FLAGS_SIZE_ERROR"); /** - * Protocol stack layers - */ -typedef enum { - LAYER_NONE = 0, - LAYER_L1, - LAYER_L2, - LAYER_L3, - LAYER_L4, - LAYER_ALL -} layer_t; - -/** * Packet parser metadata */ typedef struct { @@ -102,14 +90,6 @@ typedef struct { uint32_t l2_offset; /**< offset to L2 hdr, e.g. Eth */ uint32_t l3_offset; /**< offset to L3 hdr, e.g. IPv4, IPv6 */ uint32_t l4_offset; /**< offset to L4 hdr (TCP, UDP, SCTP, also ICMP) */ - - uint32_t l3_len; /**< Layer 3 length */ - uint32_t l4_len; /**< Layer 4 length */ - - uint16_t ethtype; /**< EtherType */ - uint8_t ip_proto; /**< IP protocol */ - uint8_t parsed_layers; /**< Highest parsed protocol stack layer */ - } packet_parser_t; /** @@ -203,16 +183,6 @@ static inline void packet_set_len(odp_packet_hdr_t *pkt_hdr, uint32_t len) pkt_hdr->frame_len = len; } -static inline int packet_parse_l2_not_done(packet_parser_t *prs) -{ - return !prs->input_flags.parsed_l2; -} - -static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr) -{ - return pkt_hdr->p.parsed_layers != LAYER_ALL; -} - /* Forward declarations */ int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt); @@ -220,11 +190,9 @@ int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt); int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, odp_packet_t pkt[], int max_num); -/* Fill in parser metadata for L2 */ -void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len); - /* Perform packet parse up to a given protocol layer */ -int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer); +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, + odp_pktio_parser_layer_t layer); /* Reset parser metadata for a new parse */ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr); @@ -264,10 +232,17 @@ static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts) } int packet_parse_common(packet_parser_t *pkt_hdr, const uint8_t *ptr, - uint32_t pkt_len, uint32_t seg_len, layer_t layer); + uint32_t pkt_len, uint32_t seg_len, + odp_pktio_parser_layer_t layer); int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr); +int _odp_packet_set_data(odp_packet_t pkt, uint32_t offset, + uint8_t c, uint32_t len); + +int _odp_packet_cmp_data(odp_packet_t pkt, uint32_t offset, + const void *s, uint32_t len); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/include/odp_packet_socket.h b/platform/linux-generic/include/odp_packet_socket.h index dbfc9f1f8..0e61f6f0c 100644 --- a/platform/linux-generic/include/odp_packet_socket.h +++ b/platform/linux-generic/include/odp_packet_socket.h @@ -27,11 +27,6 @@ * Packet socket config: */ -/** Max receive (Rx) burst size*/ -#define ODP_PACKET_SOCKET_MAX_BURST_RX 32 -/** Max transmit (Tx) burst size*/ -#define ODP_PACKET_SOCKET_MAX_BURST_TX 32 - /* * This makes sure that building for kernels older than 3.1 works * and a fanout requests fails (for invalid packet socket option) @@ -47,8 +42,6 @@ typedef struct { odp_pool_t pool; /**< pool to alloc packets from */ uint32_t mtu; /**< maximum transmission unit */ unsigned char if_mac[ETH_ALEN]; /**< IF eth mac addr */ - uint8_t *cache_ptr[ODP_PACKET_SOCKET_MAX_BURST_RX]; - odp_shm_t shm; } pkt_sock_t; /** packet mmap ring */ diff --git a/platform/linux-generic/include/odp_ring_internal.h b/platform/linux-generic/include/odp_ring_internal.h index 55fedeb3a..44b83c603 100644 --- a/platform/linux-generic/include/odp_ring_internal.h +++ b/platform/linux-generic/include/odp_ring_internal.h @@ -57,7 +57,7 @@ static inline uint32_t ring_deq(ring_t *ring, uint32_t mask) /* Move reader head. This thread owns data at the new head. */ do { - tail = odp_atomic_load_u32(&ring->w_tail); + tail = odp_atomic_load_acq_u32(&ring->w_tail); if (head == tail) return RING_EMPTY; @@ -90,7 +90,7 @@ static inline uint32_t ring_deq_multi(ring_t *ring, uint32_t mask, /* Move reader head. This thread owns data at the new head. */ do { - tail = odp_atomic_load_u32(&ring->w_tail); + tail = odp_atomic_load_acq_u32(&ring->w_tail); /* Ring is empty */ if (head == tail) diff --git a/platform/linux-generic/include/odp_time_internal.h b/platform/linux-generic/include/odp_time_internal.h new file mode 100644 index 000000000..99ac79772 --- /dev/null +++ b/platform/linux-generic/include/odp_time_internal.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2017, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_TIME_INTERNAL_H_ +#define ODP_TIME_INTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +int cpu_has_global_time(void); +uint64_t cpu_global_time(void); +uint64_t cpu_global_time_freq(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/include/protocols/ip.h b/platform/linux-generic/include/protocols/ip.h index 20041f1c0..2b34a753f 100644 --- a/platform/linux-generic/include/protocols/ip.h +++ b/platform/linux-generic/include/protocols/ip.h @@ -157,13 +157,14 @@ typedef struct ODP_PACKED { * IP protocol values (IPv4:'proto' or IPv6:'next_hdr') * @{*/ #define _ODP_IPPROTO_HOPOPTS 0x00 /**< IPv6 hop-by-hop options */ -#define _ODP_IPPROTO_ICMP 0x01 /**< Internet Control Message Protocol (1) */ +#define _ODP_IPPROTO_ICMPv4 0x01 /**< Internet Control Message Protocol (1) */ #define _ODP_IPPROTO_TCP 0x06 /**< Transmission Control Protocol (6) */ #define _ODP_IPPROTO_UDP 0x11 /**< User Datagram Protocol (17) */ #define _ODP_IPPROTO_ROUTE 0x2B /**< IPv6 Routing header (43) */ #define _ODP_IPPROTO_FRAG 0x2C /**< IPv6 Fragment (44) */ #define _ODP_IPPROTO_AH 0x33 /**< Authentication Header (51) */ #define _ODP_IPPROTO_ESP 0x32 /**< Encapsulating Security Payload (50) */ +#define _ODP_IPPROTO_ICMPv6 0x3A /**< Internet Control Message Protocol (58) */ #define _ODP_IPPROTO_SCTP 0x84 /**< Stream Control Transmission protocol (132) */ #define _ODP_IPPROTO_INVALID 0xFF /**< Reserved invalid by IANA */ diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4 index d3e5528c1..e1197f606 100644 --- a/platform/linux-generic/m4/configure.m4 +++ b/platform/linux-generic/m4/configure.m4 @@ -28,12 +28,56 @@ AC_LINK_IFELSE( echo "Use newer version. For gcc > 4.7.0" exit -1) +dnl Check whether -latomic is needed +use_libatomic=no + +AC_MSG_CHECKING(whether -latomic is needed for 64-bit atomic built-ins) +AC_LINK_IFELSE( + [AC_LANG_SOURCE([[ + static int loc; + int main(void) + { + int prev = __atomic_exchange_n(&loc, 7, __ATOMIC_RELAXED); + return 0; + } + ]])], + [AC_MSG_RESULT(no)], + [AC_MSG_RESULT(yes) + AC_CHECK_LIB( + [atomic], [__atomic_exchange_8], + [use_libatomic=yes], + [AC_MSG_FAILURE([__atomic_exchange_8 is not available])]) + ]) + +AC_MSG_CHECKING(whether -latomic is needed for 128-bit atomic built-ins) +AC_LINK_IFELSE( + [AC_LANG_SOURCE([[ + static __int128 loc; + int main(void) + { + __int128 prev; + prev = __atomic_exchange_n(&loc, 7, __ATOMIC_RELAXED); + return 0; + } + ]])], + [AC_MSG_RESULT(no)], + [AC_MSG_RESULT(yes) + AC_CHECK_LIB( + [atomic], [__atomic_exchange_16], + [use_libatomic=yes], + [AC_MSG_CHECKING([cannot detect support for 128-bit atomics])]) + ]) + +if test "x$use_libatomic" = "xyes"; then + ATOMIC_LIBS="-latomic" +fi +AC_SUBST([ATOMIC_LIBS]) + m4_include([platform/linux-generic/m4/odp_pthread.m4]) m4_include([platform/linux-generic/m4/odp_openssl.m4]) m4_include([platform/linux-generic/m4/odp_pcap.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_ipc.m4]) m4_include([platform/linux-generic/m4/odp_schedule.m4]) AC_CONFIG_FILES([platform/linux-generic/Makefile diff --git a/platform/linux-generic/m4/odp_dpdk.m4 b/platform/linux-generic/m4/odp_dpdk.m4 index 30347dce8..58d14727b 100644 --- a/platform/linux-generic/m4/odp_dpdk.m4 +++ b/platform/linux-generic/m4/odp_dpdk.m4 @@ -2,22 +2,10 @@ # Enable DPDK support ########################################################################## pktio_dpdk_support=no -AC_ARG_ENABLE([dpdk_support], - [ --enable-dpdk-support include dpdk IO support], - [if test x$enableval = xyes; then - pktio_dpdk_support=yes - fi]) - -########################################################################## -# Set optional DPDK path -########################################################################## AC_ARG_WITH([dpdk-path], -AC_HELP_STRING([--with-dpdk-path=DIR path to dpdk build directory], - [(or in the default path if not specified).]), +AC_HELP_STRING([--with-dpdk-path=DIR path to dpdk build directory]), [DPDK_PATH=$withval AM_CPPFLAGS="$AM_CPPFLAGS -msse4.2 -isystem $DPDK_PATH/include" - AM_LDFLAGS="$AM_LDFLAGS -L$DPDK_PATH/lib" - LIBS="$LIBS -ldpdk -ldl -lpcap" pktio_dpdk_support=yes],[]) ########################################################################## @@ -28,12 +16,31 @@ CPPFLAGS="$AM_CPPFLAGS $CPPFLAGS" ########################################################################## # Check for DPDK availability +# +# DPDK pmd drivers are not linked unless the --whole-archive option is +# used. No spaces are allowed between the --whole-arhive flags. ########################################################################## if test x$pktio_dpdk_support = xyes then AC_CHECK_HEADERS([rte_config.h], [], [AC_MSG_FAILURE(["can't find DPDK header"])]) + + DPDK_PMD=--whole-archive, + for filename in $with_dpdk_path/lib/*.a; do + cur_driver=`echo $(basename "$filename" .a) | \ + sed -n 's/^\(librte_pmd_\)/-lrte_pmd_/p' | sed -n 's/$/,/p'` + # rte_pmd_nfp has external dependencies which break linking + if test "$cur_driver" = "-lrte_pmd_nfp,"; then + echo "skip linking rte_pmd_nfp" + else + DPDK_PMD+=$cur_driver + fi + done + DPDK_PMD+=--no-whole-archive + ODP_CFLAGS="$ODP_CFLAGS -DODP_PKTIO_DPDK" + AM_LDFLAGS="$AM_LDFLAGS -L$DPDK_PATH/lib -Wl,$DPDK_PMD" + LIBS="$LIBS -ldpdk -ldl -lpcap" else pktio_dpdk_support=no fi diff --git a/platform/linux-generic/m4/odp_ipc.m4 b/platform/linux-generic/m4/odp_ipc.m4 deleted file mode 100644 index 78217e221..000000000 --- a/platform/linux-generic/m4/odp_ipc.m4 +++ /dev/null @@ -1,9 +0,0 @@ -########################################################################## -# Enable IPC pktio support -########################################################################## -AC_ARG_ENABLE([pktio_ipc_support], - [ --enable-pktio_ipc-support include ipc IO support], - [if test x$enableval = xyes; then - pktio_ipc_support=yes - ODP_CFLAGS="$ODP_CFLAGS -D_ODP_PKTIO_IPC" - fi]) diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c index 5d96b00b3..7ebc47d7d 100644 --- a/platform/linux-generic/odp_classification.c +++ b/platform/linux-generic/odp_classification.c @@ -790,10 +790,6 @@ static inline cos_t *cls_select_cos(pktio_entry_t *entry, cls = &entry->s.cls; default_cos = cls->default_cos; - /* Check for lazy parse needed */ - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - /* Return error cos for error packet */ if (pkt_hdr->p.error_flags.all) return cls->error_cos; @@ -838,7 +834,8 @@ int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base, packet_parse_reset(pkt_hdr); packet_set_len(pkt_hdr, pkt_len); - packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len, LAYER_ALL); + packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len, + ODP_PKTIO_PARSER_LAYER_ALL); cos = cls_select_cos(entry, base, pkt_hdr); if (cos == NULL) diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c index 54b222fd2..6fc1907d9 100644 --- a/platform/linux-generic/odp_crypto.c +++ b/platform/linux-generic/odp_crypto.c @@ -34,6 +34,9 @@ * * Keep sorted: first by key length, then by IV length */ +static const odp_crypto_cipher_capability_t cipher_capa_null[] = { +{.key_len = 0, .iv_len = 0} }; + static const odp_crypto_cipher_capability_t cipher_capa_des[] = { {.key_len = 24, .iv_len = 8} }; @@ -51,11 +54,24 @@ static const odp_crypto_cipher_capability_t cipher_capa_aes_gcm[] = { * * Keep sorted: first by digest length, then by key length */ +static const odp_crypto_auth_capability_t auth_capa_null[] = { +{.digest_len = 0, .key_len = 0, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; + static const odp_crypto_auth_capability_t auth_capa_md5_hmac[] = { -{.digest_len = 12, .key_len = 16, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; +{.digest_len = 12, .key_len = 16, .aad_len = {.min = 0, .max = 0, .inc = 0} }, +{.digest_len = 16, .key_len = 16, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; + +static const odp_crypto_auth_capability_t auth_capa_sha1_hmac[] = { +{.digest_len = 12, .key_len = 20, .aad_len = {.min = 0, .max = 0, .inc = 0} }, +{.digest_len = 20, .key_len = 20, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; static const odp_crypto_auth_capability_t auth_capa_sha256_hmac[] = { -{.digest_len = 16, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; +{.digest_len = 16, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} }, +{.digest_len = 32, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; + +static const odp_crypto_auth_capability_t auth_capa_sha512_hmac[] = { +{.digest_len = 32, .key_len = 64, .aad_len = {.min = 0, .max = 0, .inc = 0} }, +{.digest_len = 64, .key_len = 64, .aad_len = {.min = 0, .max = 0, .inc = 0} } }; static const odp_crypto_auth_capability_t auth_capa_aes_gcm[] = { {.digest_len = 16, .key_len = 0, .aad_len = {.min = 8, .max = 12, .inc = 4} } }; @@ -86,8 +102,10 @@ odp_crypto_generic_session_t *alloc_session(void) odp_spinlock_lock(&global->lock); session = global->free; - if (session) + if (session) { global->free = session->next; + session->next = NULL; + } odp_spinlock_unlock(&global->lock); return session; @@ -110,128 +128,74 @@ null_crypto_routine(odp_crypto_op_param_t *param ODP_UNUSED, } static -odp_crypto_alg_err_t md5_gen(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +void packet_hmac(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session, + uint8_t *hash) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint8_t *icv = data; + odp_packet_t pkt = param->out_pkt; + uint32_t offset = param->auth_range.offset; uint32_t len = param->auth_range.length; - uint8_t hash[EVP_MAX_MD_SIZE]; + HMAC_CTX ctx; - /* Adjust pointer for beginning of area to auth */ - data += param->auth_range.offset; - icv += param->hash_result_offset; + ODP_ASSERT(offset + len <= odp_packet_len(pkt)); /* Hash it */ - HMAC(EVP_md5(), - session->auth.data.md5.key, - 16, - data, - len, - hash, - NULL); - - /* Copy to the output location */ - memcpy(icv, hash, session->auth.data.md5.bytes); - - return ODP_CRYPTO_ALG_ERR_NONE; -} - -static -odp_crypto_alg_err_t md5_check(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) -{ - uint8_t *data = odp_packet_data(param->out_pkt); - uint8_t *icv = data; - uint32_t len = param->auth_range.length; - uint32_t bytes = session->auth.data.md5.bytes; - uint8_t hash_in[EVP_MAX_MD_SIZE]; - uint8_t hash_out[EVP_MAX_MD_SIZE]; - - /* Adjust pointer for beginning of area to auth */ - data += param->auth_range.offset; - icv += param->hash_result_offset; - - /* Copy current value out and clear it before authentication */ - memset(hash_in, 0, sizeof(hash_in)); - memcpy(hash_in, icv, bytes); - memset(icv, 0, bytes); - memset(hash_out, 0, sizeof(hash_out)); - - /* Hash it */ - HMAC(EVP_md5(), - session->auth.data.md5.key, - 16, - data, - len, - hash_out, - NULL); - - /* Verify match */ - if (0 != memcmp(hash_in, hash_out, bytes)) - return ODP_CRYPTO_ALG_ERR_ICV_CHECK; + HMAC_CTX_init(&ctx); + HMAC_Init_ex(&ctx, + session->auth.key, + session->auth.key_length, + session->auth.evp_md, + NULL); + + while (len > 0) { + uint32_t seglen = 0; /* GCC */ + void *mapaddr = odp_packet_offset(pkt, offset, &seglen, NULL); + uint32_t maclen = len > seglen ? seglen : len; + + HMAC_Update(&ctx, mapaddr, maclen); + offset += maclen; + len -= maclen; + } - /* Matched */ - return ODP_CRYPTO_ALG_ERR_NONE; + HMAC_Final(&ctx, hash, NULL); + HMAC_CTX_cleanup(&ctx); } static -odp_crypto_alg_err_t sha256_gen(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +odp_crypto_alg_err_t auth_gen(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint8_t *icv = data; - uint32_t len = param->auth_range.length; uint8_t hash[EVP_MAX_MD_SIZE]; - /* Adjust pointer for beginning of area to auth */ - data += param->auth_range.offset; - icv += param->hash_result_offset; - /* Hash it */ - HMAC(EVP_sha256(), - session->auth.data.sha256.key, - 32, - data, - len, - hash, - NULL); + packet_hmac(param, session, hash); /* Copy to the output location */ - memcpy(icv, hash, session->auth.data.sha256.bytes); + odp_packet_copy_from_mem(param->out_pkt, + param->hash_result_offset, + session->auth.bytes, + hash); return ODP_CRYPTO_ALG_ERR_NONE; } static -odp_crypto_alg_err_t sha256_check(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +odp_crypto_alg_err_t auth_check(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint8_t *icv = data; - uint32_t len = param->auth_range.length; - uint32_t bytes = session->auth.data.sha256.bytes; + uint32_t bytes = session->auth.bytes; uint8_t hash_in[EVP_MAX_MD_SIZE]; uint8_t hash_out[EVP_MAX_MD_SIZE]; - /* Adjust pointer for beginning of area to auth */ - data += param->auth_range.offset; - icv += param->hash_result_offset; - /* Copy current value out and clear it before authentication */ - memset(hash_in, 0, sizeof(hash_in)); - memcpy(hash_in, icv, bytes); - memset(icv, 0, bytes); - memset(hash_out, 0, sizeof(hash_out)); + odp_packet_copy_to_mem(param->out_pkt, param->hash_result_offset, + bytes, hash_in); + + _odp_packet_set_data(param->out_pkt, param->hash_result_offset, + 0, bytes); /* Hash it */ - HMAC(EVP_sha256(), - session->auth.data.sha256.key, - 32, - data, - len, - hash_out, - NULL); + packet_hmac(param, session, hash_out); /* Verify match */ if (0 != memcmp(hash_in, hash_out, bytes)) @@ -242,102 +206,122 @@ odp_crypto_alg_err_t sha256_check(odp_crypto_op_param_t *param, } static -odp_crypto_alg_err_t aes_encrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +int internal_encrypt(EVP_CIPHER_CTX *ctx, odp_crypto_op_param_t *param) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t len = param->cipher_range.length; - unsigned char iv_enc[AES_BLOCK_SIZE]; - void *iv_ptr; + odp_packet_t pkt = param->out_pkt; + unsigned in_pos = param->cipher_range.offset; + unsigned out_pos = param->cipher_range.offset; + unsigned in_len = param->cipher_range.length; + uint8_t block[2 * EVP_MAX_BLOCK_LENGTH]; + unsigned block_len = EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(ctx)); + int cipher_len; + int ret; - if (param->override_iv_ptr) - iv_ptr = param->override_iv_ptr; - else if (session->p.iv.data) - iv_ptr = session->cipher.iv_data; - else - return ODP_CRYPTO_ALG_ERR_IV_INVALID; + while (in_len > 0) { + uint32_t seglen = 0; /* GCC */ + uint8_t *insegaddr = odp_packet_offset(pkt, in_pos, + &seglen, NULL); + unsigned inseglen = in_len < seglen ? in_len : seglen; - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE); + /* There should be at least 1 additional block in out buffer */ + if (inseglen > block_len) { + unsigned part = inseglen - block_len; - /* Adjust pointer for beginning of area to cipher */ - data += param->cipher_range.offset; - /* Encrypt it */ - AES_cbc_encrypt(data, data, len, &session->cipher.data.aes.key, - iv_enc, AES_ENCRYPT); + EVP_EncryptUpdate(ctx, insegaddr, &cipher_len, + insegaddr, part); + in_pos += part; + in_len -= part; + insegaddr += part; + inseglen -= part; - return ODP_CRYPTO_ALG_ERR_NONE; + out_pos += cipher_len; + } + + /* Use temporal storage */ + if (inseglen > 0) { + unsigned part = inseglen; + + EVP_EncryptUpdate(ctx, block, &cipher_len, + insegaddr, part); + in_pos += part; + in_len -= part; + insegaddr += part; + inseglen -= part; + + odp_packet_copy_from_mem(pkt, out_pos, + cipher_len, block); + out_pos += cipher_len; + } + } + + ret = EVP_EncryptFinal_ex(ctx, block, &cipher_len); + odp_packet_copy_from_mem(pkt, out_pos, cipher_len, block); + + return ret; } static -odp_crypto_alg_err_t aes_decrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +int internal_decrypt(EVP_CIPHER_CTX *ctx, odp_crypto_op_param_t *param) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t len = param->cipher_range.length; - unsigned char iv_enc[AES_BLOCK_SIZE]; - void *iv_ptr; + odp_packet_t pkt = param->out_pkt; + unsigned in_pos = param->cipher_range.offset; + unsigned out_pos = param->cipher_range.offset; + unsigned in_len = param->cipher_range.length; + uint8_t block[2 * EVP_MAX_BLOCK_LENGTH]; + unsigned block_len = EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(ctx)); + int cipher_len; + int ret; - if (param->override_iv_ptr) - iv_ptr = param->override_iv_ptr; - else if (session->p.iv.data) - iv_ptr = session->cipher.iv_data; - else - return ODP_CRYPTO_ALG_ERR_IV_INVALID; + while (in_len > 0) { + uint32_t seglen = 0; /* GCC */ + uint8_t *insegaddr = odp_packet_offset(pkt, in_pos, + &seglen, NULL); + unsigned inseglen = in_len < seglen ? in_len : seglen; - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE); + /* There should be at least 1 additional block in out buffer */ + if (inseglen > block_len) { + unsigned part = inseglen - block_len; - /* Adjust pointer for beginning of area to cipher */ - data += param->cipher_range.offset; - /* Encrypt it */ - AES_cbc_encrypt(data, data, len, &session->cipher.data.aes.key, - iv_enc, AES_DECRYPT); + EVP_DecryptUpdate(ctx, insegaddr, &cipher_len, + insegaddr, part); + in_pos += part; + in_len -= part; + insegaddr += part; + inseglen -= part; - return ODP_CRYPTO_ALG_ERR_NONE; -} + out_pos += cipher_len; + } -static int process_aes_param(odp_crypto_generic_session_t *session) -{ - /* Verify IV len is either 0 or 16 */ - if (!((0 == session->p.iv.length) || (16 == session->p.iv.length))) - return -1; + /* Use temporal storage */ + if (inseglen > 0) { + unsigned part = inseglen; - /* Set function */ - if (ODP_CRYPTO_OP_ENCODE == session->p.op) { - session->cipher.func = aes_encrypt; - AES_set_encrypt_key(session->p.cipher_key.data, 128, - &session->cipher.data.aes.key); - } else { - session->cipher.func = aes_decrypt; - AES_set_decrypt_key(session->p.cipher_key.data, 128, - &session->cipher.data.aes.key); + EVP_DecryptUpdate(ctx, block, &cipher_len, + insegaddr, part); + in_pos += part; + in_len -= part; + insegaddr += part; + inseglen -= part; + + odp_packet_copy_from_mem(pkt, out_pos, + cipher_len, block); + out_pos += cipher_len; + } } - return 0; + ret = EVP_DecryptFinal_ex(ctx, block, &cipher_len); + odp_packet_copy_from_mem(pkt, out_pos, cipher_len, block); + + return ret; } static -odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +odp_crypto_alg_err_t cipher_encrypt(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t plain_len = param->cipher_range.length; - uint8_t *aad_head = data + param->auth_range.offset; - uint8_t *aad_tail = data + param->cipher_range.offset + - param->cipher_range.length; - uint32_t auth_len = param->auth_range.length; - unsigned char iv_enc[AES_BLOCK_SIZE]; + EVP_CIPHER_CTX *ctx; void *iv_ptr; - uint8_t *tag = data + param->hash_result_offset; + int ret; if (param->override_iv_ptr) iv_ptr = param->override_iv_ptr; @@ -346,63 +330,28 @@ odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param, else return ODP_CRYPTO_ALG_ERR_IV_INVALID; - /* All cipher data must be part of the authentication */ - if (param->auth_range.offset > param->cipher_range.offset || - param->auth_range.offset + auth_len < - param->cipher_range.offset + plain_len) - return ODP_CRYPTO_ALG_ERR_DATA_SIZE; - - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE); - - /* Adjust pointer for beginning of area to cipher/auth */ - uint8_t *plaindata = data + param->cipher_range.offset; - /* Encrypt it */ - EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx; - int cipher_len = 0; - - EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_enc); - - /* Authenticate header data (if any) without encrypting them */ - if (aad_head < plaindata) { - EVP_EncryptUpdate(ctx, NULL, &cipher_len, - aad_head, plaindata - aad_head); - } + ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(ctx, session->cipher.evp_cipher, NULL, + session->cipher.key_data, NULL); + EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr); + EVP_CIPHER_CTX_set_padding(ctx, 0); - EVP_EncryptUpdate(ctx, plaindata, &cipher_len, - plaindata, plain_len); - cipher_len = plain_len; + ret = internal_encrypt(ctx, param); - /* Authenticate footer data (if any) without encrypting them */ - if (aad_head + auth_len > plaindata + plain_len) { - EVP_EncryptUpdate(ctx, NULL, NULL, aad_tail, - auth_len - (aad_tail - aad_head)); - } + EVP_CIPHER_CTX_free(ctx); - EVP_EncryptFinal_ex(ctx, plaindata + cipher_len, &cipher_len); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag); - - return ODP_CRYPTO_ALG_ERR_NONE; + return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE : + ODP_CRYPTO_ALG_ERR_NONE; } static -odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +odp_crypto_alg_err_t cipher_decrypt(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t cipher_len = param->cipher_range.length; - uint8_t *aad_head = data + param->auth_range.offset; - uint8_t *aad_tail = data + param->cipher_range.offset + - param->cipher_range.length; - uint32_t auth_len = param->auth_range.length; - unsigned char iv_enc[AES_BLOCK_SIZE]; + EVP_CIPHER_CTX *ctx; void *iv_ptr; - uint8_t *tag = data + param->hash_result_offset; + int ret; if (param->override_iv_ptr) iv_ptr = param->override_iv_ptr; @@ -411,90 +360,59 @@ odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param, else return ODP_CRYPTO_ALG_ERR_IV_INVALID; - /* All cipher data must be part of the authentication */ - if (param->auth_range.offset > param->cipher_range.offset || - param->auth_range.offset + auth_len < - param->cipher_range.offset + cipher_len) - return ODP_CRYPTO_ALG_ERR_DATA_SIZE; - - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE); - - /* Adjust pointer for beginning of area to cipher/auth */ - uint8_t *cipherdata = data + param->cipher_range.offset; - /* Encrypt it */ - EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx; - int plain_len = 0; - - EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_enc); - - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag); - - /* Authenticate header data (if any) without encrypting them */ - if (aad_head < cipherdata) { - EVP_DecryptUpdate(ctx, NULL, &plain_len, - aad_head, cipherdata - aad_head); - } - - EVP_DecryptUpdate(ctx, cipherdata, &plain_len, - cipherdata, cipher_len); - plain_len = cipher_len; + /* Decrypt it */ + ctx = EVP_CIPHER_CTX_new(); + EVP_DecryptInit_ex(ctx, session->cipher.evp_cipher, NULL, + session->cipher.key_data, NULL); + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr); + EVP_CIPHER_CTX_set_padding(ctx, 0); - /* Authenticate footer data (if any) without encrypting them */ - if (aad_head + auth_len > cipherdata + cipher_len) { - EVP_DecryptUpdate(ctx, NULL, NULL, aad_tail, - auth_len - (aad_tail - aad_head)); - } + ret = internal_decrypt(ctx, param); - if (EVP_DecryptFinal_ex(ctx, cipherdata + cipher_len, &plain_len) < 0) - return ODP_CRYPTO_ALG_ERR_ICV_CHECK; + EVP_CIPHER_CTX_free(ctx); - return ODP_CRYPTO_ALG_ERR_NONE; + return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE : + ODP_CRYPTO_ALG_ERR_NONE; } -static int process_aes_gcm_param(odp_crypto_generic_session_t *session) +static int process_cipher_param(odp_crypto_generic_session_t *session, + const EVP_CIPHER *cipher) { - /* Verify Key len is 16 */ - if (session->p.cipher_key.length != 16) + /* Verify Key len is valid */ + if ((uint32_t)EVP_CIPHER_key_length(cipher) != + session->p.cipher_key.length) return -1; - /* Set function */ - EVP_CIPHER_CTX *ctx = - session->cipher.data.aes_gcm.ctx = EVP_CIPHER_CTX_new(); + /* Verify IV len is correct */ + if (!((0 == session->p.iv.length) || + ((uint32_t)EVP_CIPHER_iv_length(cipher) == session->p.iv.length))) + return -1; - if (ODP_CRYPTO_OP_ENCODE == session->p.op) { - session->cipher.func = aes_gcm_encrypt; - EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); - } else { - session->cipher.func = aes_gcm_decrypt; - EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); - } + session->cipher.evp_cipher = cipher; - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, - session->p.iv.length, NULL); - if (ODP_CRYPTO_OP_ENCODE == session->p.op) { - EVP_EncryptInit_ex(ctx, NULL, NULL, - session->p.cipher_key.data, NULL); - } else { - EVP_DecryptInit_ex(ctx, NULL, NULL, - session->p.cipher_key.data, NULL); - } + memcpy(session->cipher.key_data, session->p.cipher_key.data, + session->p.cipher_key.length); + + /* Set function */ + if (ODP_CRYPTO_OP_ENCODE == session->p.op) + session->cipher.func = cipher_encrypt; + else + session->cipher.func = cipher_decrypt; return 0; } static -odp_crypto_alg_err_t des_encrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t len = param->cipher_range.length; - DES_cblock iv; + EVP_CIPHER_CTX *ctx; + const uint8_t *aad_head = param->aad.ptr; + uint32_t aad_len = param->aad.length; void *iv_ptr; + int dummy_len = 0; + uint8_t block[EVP_MAX_MD_SIZE]; + int ret; if (param->override_iv_ptr) iv_ptr = param->override_iv_ptr; @@ -503,36 +421,44 @@ odp_crypto_alg_err_t des_encrypt(odp_crypto_op_param_t *param, else return ODP_CRYPTO_ALG_ERR_IV_INVALID; - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv, iv_ptr, sizeof(iv)); - - /* Adjust pointer for beginning of area to cipher */ - data += param->cipher_range.offset; /* Encrypt it */ - DES_ede3_cbc_encrypt(data, - data, - len, - &session->cipher.data.des.ks1, - &session->cipher.data.des.ks2, - &session->cipher.data.des.ks3, - &iv, - 1); + ctx = EVP_CIPHER_CTX_new(); + EVP_EncryptInit_ex(ctx, session->cipher.evp_cipher, NULL, + session->cipher.key_data, NULL); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, + session->p.iv.length, NULL); + EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr); + EVP_CIPHER_CTX_set_padding(ctx, 0); - return ODP_CRYPTO_ALG_ERR_NONE; + /* Authenticate header data (if any) without encrypting them */ + if (aad_len > 0) + EVP_EncryptUpdate(ctx, NULL, &dummy_len, + aad_head, aad_len); + + ret = internal_encrypt(ctx, param); + + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, + session->p.auth_digest_len, block); + odp_packet_copy_from_mem(param->out_pkt, param->hash_result_offset, + session->p.auth_digest_len, block); + + EVP_CIPHER_CTX_free(ctx); + + return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE : + ODP_CRYPTO_ALG_ERR_NONE; } static -odp_crypto_alg_err_t des_decrypt(odp_crypto_op_param_t *param, - odp_crypto_generic_session_t *session) +odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param, + odp_crypto_generic_session_t *session) { - uint8_t *data = odp_packet_data(param->out_pkt); - uint32_t len = param->cipher_range.length; - DES_cblock iv; + EVP_CIPHER_CTX *ctx; + const uint8_t *aad_head = param->aad.ptr; + uint32_t aad_len = param->aad.length; + int dummy_len = 0; void *iv_ptr; + uint8_t block[EVP_MAX_MD_SIZE]; + int ret; if (param->override_iv_ptr) iv_ptr = param->override_iv_ptr; @@ -541,84 +467,76 @@ odp_crypto_alg_err_t des_decrypt(odp_crypto_op_param_t *param, else return ODP_CRYPTO_ALG_ERR_IV_INVALID; - /* - * Create a copy of the IV. The DES library modifies IV - * and if we are processing packets on parallel threads - * we could get corruption. - */ - memcpy(iv, iv_ptr, sizeof(iv)); + /* Decrypt it */ + ctx = EVP_CIPHER_CTX_new(); + EVP_DecryptInit_ex(ctx, session->cipher.evp_cipher, NULL, + session->cipher.key_data, NULL); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, + session->p.iv.length, NULL); + EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr); + EVP_CIPHER_CTX_set_padding(ctx, 0); - /* Adjust pointer for beginning of area to cipher */ - data += param->cipher_range.offset; + odp_packet_copy_to_mem(param->out_pkt, param->hash_result_offset, + session->p.auth_digest_len, block); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, + session->p.auth_digest_len, block); - /* Decrypt it */ - DES_ede3_cbc_encrypt(data, - data, - len, - &session->cipher.data.des.ks1, - &session->cipher.data.des.ks2, - &session->cipher.data.des.ks3, - &iv, - 0); + /* Authenticate header data (if any) without encrypting them */ + if (aad_len > 0) + EVP_DecryptUpdate(ctx, NULL, &dummy_len, + aad_head, aad_len); - return ODP_CRYPTO_ALG_ERR_NONE; + ret = internal_decrypt(ctx, param); + + EVP_CIPHER_CTX_free(ctx); + + return ret <= 0 ? ODP_CRYPTO_ALG_ERR_ICV_CHECK : + ODP_CRYPTO_ALG_ERR_NONE; } -static int process_des_param(odp_crypto_generic_session_t *session) +static int process_aes_gcm_param(odp_crypto_generic_session_t *session, + const EVP_CIPHER *cipher) { - /* Verify IV len is either 0 or 8 */ - if (!((0 == session->p.iv.length) || (8 == session->p.iv.length))) + /* Verify Key len is valid */ + if ((uint32_t)EVP_CIPHER_key_length(cipher) != + session->p.cipher_key.length) return -1; - /* Set function */ - if (ODP_CRYPTO_OP_ENCODE == session->p.op) - session->cipher.func = des_encrypt; - else - session->cipher.func = des_decrypt; + memcpy(session->cipher.key_data, session->p.cipher_key.data, + session->p.cipher_key.length); - /* Convert keys */ - DES_set_key((DES_cblock *)&session->p.cipher_key.data[0], - &session->cipher.data.des.ks1); - DES_set_key((DES_cblock *)&session->p.cipher_key.data[8], - &session->cipher.data.des.ks2); - DES_set_key((DES_cblock *)&session->p.cipher_key.data[16], - &session->cipher.data.des.ks3); + session->cipher.evp_cipher = cipher; - return 0; -} - -static int process_md5_param(odp_crypto_generic_session_t *session, - uint32_t bits) -{ /* Set function */ if (ODP_CRYPTO_OP_ENCODE == session->p.op) - session->auth.func = md5_gen; + session->cipher.func = aes_gcm_encrypt; else - session->auth.func = md5_check; - - /* Number of valid bytes */ - session->auth.data.md5.bytes = bits / 8; - - /* Convert keys */ - memcpy(session->auth.data.md5.key, session->p.auth_key.data, 16); + session->cipher.func = aes_gcm_decrypt; return 0; } -static int process_sha256_param(odp_crypto_generic_session_t *session, - uint32_t bits) +static int process_auth_param(odp_crypto_generic_session_t *session, + uint32_t key_length, + const EVP_MD *evp_md) { /* Set function */ if (ODP_CRYPTO_OP_ENCODE == session->p.op) - session->auth.func = sha256_gen; + session->auth.func = auth_gen; else - session->auth.func = sha256_check; + session->auth.func = auth_check; + + session->auth.evp_md = evp_md; /* Number of valid bytes */ - session->auth.data.sha256.bytes = bits / 8; + session->auth.bytes = session->p.auth_digest_len; + if (session->auth.bytes < (unsigned)EVP_MD_size(evp_md) / 2) + return -1; /* Convert keys */ - memcpy(session->auth.data.sha256.key, session->p.auth_key.data, 32); + session->auth.key_length = key_length; + memcpy(session->auth.key, session->p.auth_key.data, + session->auth.key_length); return 0; } @@ -639,15 +557,18 @@ int odp_crypto_capability(odp_crypto_capability_t *capa) capa->auths.bit.null = 1; capa->auths.bit.md5_hmac = 1; + capa->auths.bit.sha1_hmac = 1; capa->auths.bit.sha256_hmac = 1; + capa->auths.bit.sha512_hmac = 1; capa->auths.bit.aes_gcm = 1; - /* Deprecated */ +#if ODP_DEPRECATED_API capa->ciphers.bit.aes128_cbc = 1; capa->ciphers.bit.aes128_gcm = 1; capa->auths.bit.md5_96 = 1; capa->auths.bit.sha256_128 = 1; capa->auths.bit.aes128_gcm = 1; +#endif capa->max_sessions = MAX_SESSIONS; @@ -664,8 +585,8 @@ int odp_crypto_cipher_capability(odp_cipher_alg_t cipher, switch (cipher) { case ODP_CIPHER_ALG_NULL: - src = NULL; - num = 0; + src = cipher_capa_null; + num = sizeof(cipher_capa_null) / size; break; case ODP_CIPHER_ALG_DES: src = cipher_capa_des; @@ -704,17 +625,25 @@ int odp_crypto_auth_capability(odp_auth_alg_t auth, switch (auth) { case ODP_AUTH_ALG_NULL: - src = NULL; - num = 0; + src = auth_capa_null; + num = sizeof(auth_capa_null) / size; break; case ODP_AUTH_ALG_MD5_HMAC: src = auth_capa_md5_hmac; num = sizeof(auth_capa_md5_hmac) / size; break; + case ODP_AUTH_ALG_SHA1_HMAC: + src = auth_capa_sha1_hmac; + num = sizeof(auth_capa_sha1_hmac) / size; + break; case ODP_AUTH_ALG_SHA256_HMAC: src = auth_capa_sha256_hmac; num = sizeof(auth_capa_sha256_hmac) / size; break; + case ODP_AUTH_ALG_SHA512_HMAC: + src = auth_capa_sha512_hmac; + num = sizeof(auth_capa_sha512_hmac) / size; + break; case ODP_AUTH_ALG_AES_GCM: src = auth_capa_aes_gcm; num = sizeof(auth_capa_aes_gcm) / size; @@ -738,6 +667,7 @@ odp_crypto_session_create(odp_crypto_session_param_t *param, { int rc; odp_crypto_generic_session_t *session; + int aes_gcm = 0; /* Default to successful result */ *status = ODP_CRYPTO_SES_CREATE_ERR_NONE; @@ -752,16 +682,16 @@ odp_crypto_session_create(odp_crypto_session_param_t *param, /* Copy parameters */ session->p = *param; - /* Copy IV data */ - if (session->p.iv.data) { - if (session->p.iv.length > MAX_IV_LEN) { - ODP_DBG("Maximum IV length exceeded\n"); - return -1; - } + if (session->p.iv.length > MAX_IV_LEN) { + ODP_DBG("Maximum IV length exceeded\n"); + free_session(session); + return -1; + } + /* Copy IV data */ + if (session->p.iv.data) memcpy(session->cipher.iv_data, session->p.iv.data, session->p.iv.length); - } /* Derive order */ if (ODP_CRYPTO_OP_ENCODE == param->op) @@ -777,21 +707,25 @@ odp_crypto_session_create(odp_crypto_session_param_t *param, break; case ODP_CIPHER_ALG_DES: case ODP_CIPHER_ALG_3DES_CBC: - rc = process_des_param(session); + rc = process_cipher_param(session, EVP_des_ede3_cbc()); break; case ODP_CIPHER_ALG_AES_CBC: - /* deprecated */ +#if ODP_DEPRECATED_API case ODP_CIPHER_ALG_AES128_CBC: - rc = process_aes_param(session); +#endif + rc = process_cipher_param(session, EVP_aes_128_cbc()); break; - case ODP_CIPHER_ALG_AES_GCM: - /* deprecated */ +#if ODP_DEPRECATED_API case ODP_CIPHER_ALG_AES128_GCM: + if (param->auth_alg == ODP_AUTH_ALG_AES128_GCM) + aes_gcm = 1; + /* Fallthrough */ +#endif + case ODP_CIPHER_ALG_AES_GCM: /* AES-GCM requires to do both auth and * cipher at the same time */ - if (param->auth_alg == ODP_AUTH_ALG_AES_GCM || - param->auth_alg == ODP_AUTH_ALG_AES128_GCM) - rc = process_aes_gcm_param(session); + if (param->auth_alg == ODP_AUTH_ALG_AES_GCM || aes_gcm) + rc = process_aes_gcm_param(session, EVP_aes_128_gcm()); else rc = -1; break; @@ -802,32 +736,54 @@ odp_crypto_session_create(odp_crypto_session_param_t *param, /* Check result */ if (rc) { *status = ODP_CRYPTO_SES_CREATE_ERR_INV_CIPHER; + free_session(session); return -1; } + aes_gcm = 0; + /* Process based on auth */ switch (param->auth_alg) { case ODP_AUTH_ALG_NULL: session->auth.func = null_crypto_routine; rc = 0; break; - case ODP_AUTH_ALG_MD5_HMAC: - /* deprecated */ +#if ODP_DEPRECATED_API case ODP_AUTH_ALG_MD5_96: - rc = process_md5_param(session, 96); + /* Fixed digest tag length with deprecated algo */ + session->p.auth_digest_len = 96 / 8; + /* Fallthrough */ +#endif + case ODP_AUTH_ALG_MD5_HMAC: + rc = process_auth_param(session, 16, EVP_md5()); break; - case ODP_AUTH_ALG_SHA256_HMAC: - /* deprecated */ + case ODP_AUTH_ALG_SHA1_HMAC: + rc = process_auth_param(session, 20, EVP_sha1()); + break; +#if ODP_DEPRECATED_API case ODP_AUTH_ALG_SHA256_128: - rc = process_sha256_param(session, 128); + /* Fixed digest tag length with deprecated algo */ + session->p.auth_digest_len = 128 / 8; + /* Fallthrough */ +#endif + case ODP_AUTH_ALG_SHA256_HMAC: + rc = process_auth_param(session, 32, EVP_sha256()); break; - case ODP_AUTH_ALG_AES_GCM: - /* deprecated */ + case ODP_AUTH_ALG_SHA512_HMAC: + rc = process_auth_param(session, 64, EVP_sha512()); + break; +#if ODP_DEPRECATED_API case ODP_AUTH_ALG_AES128_GCM: + if (param->cipher_alg == ODP_CIPHER_ALG_AES128_GCM) + aes_gcm = 1; + /* Fixed digest tag length with deprecated algo */ + session->p.auth_digest_len = 16; + /* Fallthrough */ +#endif + case ODP_AUTH_ALG_AES_GCM: /* AES-GCM requires to do both auth and * cipher at the same time */ - if (param->cipher_alg == ODP_CIPHER_ALG_AES_GCM || - param->cipher_alg == ODP_CIPHER_ALG_AES128_GCM) { + if (param->cipher_alg == ODP_CIPHER_ALG_AES_GCM || aes_gcm) { session->auth.func = null_crypto_routine; rc = 0; } else { @@ -841,6 +797,7 @@ odp_crypto_session_create(odp_crypto_session_param_t *param, /* Check result */ if (rc) { *status = ODP_CRYPTO_SES_CREATE_ERR_INV_AUTH; + free_session(session); return -1; } @@ -854,9 +811,6 @@ int odp_crypto_session_destroy(odp_crypto_session_t session) odp_crypto_generic_session_t *generic; generic = (odp_crypto_generic_session_t *)(intptr_t)session; - if (generic->p.cipher_alg == ODP_CIPHER_ALG_AES128_GCM || - generic->p.cipher_alg == ODP_CIPHER_ALG_AES_GCM) - EVP_CIPHER_CTX_free(generic->cipher.data.aes_gcm.ctx); memset(generic, 0, sizeof(*generic)); free_session(generic); return 0; @@ -871,14 +825,17 @@ odp_crypto_operation(odp_crypto_op_param_t *param, odp_crypto_alg_err_t rc_auth = ODP_CRYPTO_ALG_ERR_NONE; odp_crypto_generic_session_t *session; odp_crypto_op_result_t local_result; + odp_bool_t allocated = false; session = (odp_crypto_generic_session_t *)(intptr_t)param->session; /* Resolve output buffer */ if (ODP_PACKET_INVALID == param->out_pkt && - ODP_POOL_INVALID != session->p.output_pool) + ODP_POOL_INVALID != session->p.output_pool) { param->out_pkt = odp_packet_alloc(session->p.output_pool, odp_packet_len(param->pkt)); + allocated = true; + } if (odp_unlikely(ODP_PACKET_INVALID == param->out_pkt)) { ODP_DBG("Alloc failed.\n"); @@ -886,11 +843,16 @@ odp_crypto_operation(odp_crypto_op_param_t *param, } if (param->pkt != param->out_pkt) { - (void)odp_packet_copy_from_pkt(param->out_pkt, + int ret; + + ret = odp_packet_copy_from_pkt(param->out_pkt, 0, param->pkt, 0, odp_packet_len(param->pkt)); + if (odp_unlikely(ret < 0)) + goto err; + _odp_packet_copy_md_to_packet(param->pkt, param->out_pkt); odp_packet_free(param->pkt); param->pkt = ODP_PACKET_INVALID; @@ -932,7 +894,7 @@ odp_crypto_operation(odp_crypto_op_param_t *param, op_result->result = local_result; if (odp_queue_enq(session->p.compl_queue, completion_event)) { odp_event_free(completion_event); - return -1; + goto err; } /* Indicate to caller operation was async */ @@ -940,13 +902,21 @@ odp_crypto_operation(odp_crypto_op_param_t *param, } else { /* Synchronous, simply return results */ if (!result) - return -1; + goto err; *result = local_result; /* Indicate to caller operation was sync */ *posted = 0; } return 0; + +err: + if (allocated) { + odp_packet_free(param->out_pkt); + param->out_pkt = ODP_PACKET_INVALID; + } + + return -1; } static void ODP_UNUSED openssl_thread_id(CRYPTO_THREADID ODP_UNUSED *id) diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 17a51b069..eb66af2d3 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -24,6 +24,8 @@ /* Initial packet segment data length */ #define BASE_LEN CONFIG_PACKET_MAX_SEG_LEN +#include <odp/visibility_begin.h> + /* Fill in packet header field offsets for inline functions */ const _odp_packet_inline_offset_t _odp_packet_inline ODP_ALIGNED_CACHE = { .data = offsetof(odp_packet_hdr_t, buf_hdr.seg[0].data), @@ -43,6 +45,8 @@ const _odp_packet_inline_offset_t _odp_packet_inline ODP_ALIGNED_CACHE = { }; +#include <odp/visibility_end.h> + static inline odp_packet_hdr_t *packet_hdr(odp_packet_t pkt) { return (odp_packet_hdr_t *)(uintptr_t)pkt; @@ -216,16 +220,9 @@ static inline void *packet_map(odp_packet_hdr_t *pkt_hdr, return addr; } -static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr) -{ - pkt_hdr->p.input_flags.parsed_l2 = 1; - pkt_hdr->p.parsed_layers = LAYER_ALL; -} - void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) { /* Reset parser metadata before new parse */ - pkt_hdr->p.parsed_layers = LAYER_NONE; pkt_hdr->p.error_flags.all = 0; pkt_hdr->p.input_flags.all = 0; pkt_hdr->p.output_flags.all = 0; @@ -237,8 +234,7 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) /** * Initialize packet */ -static inline void packet_init(odp_packet_hdr_t *pkt_hdr, uint32_t len, - int parse) +static inline void packet_init(odp_packet_hdr_t *pkt_hdr, uint32_t len) { uint32_t seg_len; int num = pkt_hdr->buf_hdr.segcount; @@ -253,7 +249,6 @@ static inline void packet_init(odp_packet_hdr_t *pkt_hdr, uint32_t len, pkt_hdr->buf_hdr.seg[num - 1].len = seg_len; } - pkt_hdr->p.parsed_layers = LAYER_NONE; pkt_hdr->p.input_flags.all = 0; pkt_hdr->p.output_flags.all = 0; pkt_hdr->p.error_flags.all = 0; @@ -262,10 +257,6 @@ static inline void packet_init(odp_packet_hdr_t *pkt_hdr, uint32_t len, pkt_hdr->p.l3_offset = ODP_PACKET_OFFSET_INVALID; pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID; - /* Disable lazy parsing on user allocated packets */ - if (!parse) - packet_parse_disable(pkt_hdr); - /* * Packet headroom is set from the pool's headroom * Packet tailroom is rounded up to fill the last @@ -481,7 +472,7 @@ static inline odp_packet_hdr_t *free_segments(odp_packet_hdr_t *pkt_hdr, } static inline int packet_alloc(pool_t *pool, uint32_t len, int max_pkt, - int num_seg, odp_packet_t *pkt, int parse) + int num_seg, odp_packet_t *pkt) { int num_buf, i; int num = max_pkt; @@ -514,7 +505,7 @@ static inline int packet_alloc(pool_t *pool, uint32_t len, int max_pkt, pkt[i] = packet_handle(hdr); init_segments(&pkt_hdr[i * num_seg], num_seg); - packet_init(hdr, len, parse); + packet_init(hdr, len); } return num; @@ -527,7 +518,7 @@ int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, int num, num_seg; num_seg = num_segments(len); - num = packet_alloc(pool, len, max_num, num_seg, pkt, 1); + num = packet_alloc(pool, len, max_num, num_seg, pkt); return num; } @@ -547,7 +538,7 @@ odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) return ODP_PACKET_INVALID; num_seg = num_segments(len); - num = packet_alloc(pool, len, 1, num_seg, &pkt, 0); + num = packet_alloc(pool, len, 1, num_seg, &pkt); if (odp_unlikely(num == 0)) return ODP_PACKET_INVALID; @@ -570,7 +561,7 @@ int odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, return -1; num_seg = num_segments(len); - num = packet_alloc(pool, len, max_num, num_seg, pkt, 0); + num = packet_alloc(pool, len, max_num, num_seg, pkt); return num; } @@ -590,11 +581,16 @@ void odp_packet_free(odp_packet_t pkt) void odp_packet_free_multi(const odp_packet_t pkt[], int num) { + odp_buffer_t buf[num * CONFIG_PACKET_MAX_SEGS]; + int i; + if (CONFIG_PACKET_MAX_SEGS == 1) { - buffer_free_multi((const odp_buffer_t * const)pkt, num); + for (i = 0; i < num; i++) + buf[i] = buffer_handle(packet_hdr(pkt[i])); + + buffer_free_multi(buf, num); } else { - odp_buffer_t buf[num * CONFIG_PACKET_MAX_SEGS]; - int i, j; + int j; int bufs = 0; for (i = 0; i < num; i++) { @@ -626,7 +622,7 @@ int odp_packet_reset(odp_packet_t pkt, uint32_t len) if (len > pool->headroom + pool->data_size + pool->tailroom) return -1; - packet_init(pkt_hdr, len, 0); + packet_init(pkt_hdr, len); return 0; } @@ -795,7 +791,8 @@ static inline int move_data_to_head(odp_packet_hdr_t *pkt_hdr, int segs) free_len = BASE_LEN - len; - for (src_seg = dst_seg + 1; src_seg < segs; src_seg++) { + for (src_seg = dst_seg + 1; CONFIG_PACKET_MAX_SEGS > 1 && + src_seg < segs; src_seg++) { len = fill_seg_head(pkt_hdr, dst_seg, src_seg, free_len); moved += len; @@ -919,7 +916,7 @@ int odp_packet_extend_head(odp_packet_t *pkt, uint32_t len, pkt_hdr = new_hdr; *pkt = packet_handle(pkt_hdr); - } else if (free_segs) { + } else if (CONFIG_PACKET_MAX_SEGS > 1 && free_segs) { new_hdr = pkt_hdr->buf_hdr.seg[free_segs].hdr; packet_seg_copy_md(new_hdr, pkt_hdr); @@ -1237,8 +1234,6 @@ void *odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L3) - packet_parse_layer(pkt_hdr, LAYER_L3); return packet_map(pkt_hdr, pkt_hdr->p.l3_offset, len, NULL); } @@ -1246,8 +1241,6 @@ uint32_t odp_packet_l3_offset(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L3) - packet_parse_layer(pkt_hdr, LAYER_L3); return pkt_hdr->p.l3_offset; } @@ -1258,8 +1251,6 @@ int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset) if (offset >= pkt_hdr->frame_len) return -1; - if (pkt_hdr->p.parsed_layers < LAYER_L3) - packet_parse_layer(pkt_hdr, LAYER_L3); pkt_hdr->p.l3_offset = offset; return 0; } @@ -1268,8 +1259,6 @@ void *odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L4) - packet_parse_layer(pkt_hdr, LAYER_L4); return packet_map(pkt_hdr, pkt_hdr->p.l4_offset, len, NULL); } @@ -1277,8 +1266,6 @@ uint32_t odp_packet_l4_offset(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L4) - packet_parse_layer(pkt_hdr, LAYER_L4); return pkt_hdr->p.l4_offset; } @@ -1289,8 +1276,6 @@ int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset) if (offset >= pkt_hdr->frame_len) return -1; - if (pkt_hdr->p.parsed_layers < LAYER_L4) - packet_parse_layer(pkt_hdr, LAYER_L4); pkt_hdr->p.l4_offset = offset; return 0; } @@ -1655,6 +1640,54 @@ int odp_packet_move_data(odp_packet_t pkt, uint32_t dst_offset, pkt, src_offset, len); } +int _odp_packet_set_data(odp_packet_t pkt, uint32_t offset, + uint8_t c, uint32_t len) +{ + void *mapaddr; + uint32_t seglen = 0; /* GCC */ + uint32_t setlen; + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + + if (offset + len > pkt_hdr->frame_len) + return -1; + + while (len > 0) { + mapaddr = packet_map(pkt_hdr, offset, &seglen, NULL); + setlen = len > seglen ? seglen : len; + memset(mapaddr, c, setlen); + offset += setlen; + len -= setlen; + } + + return 0; +} + +int _odp_packet_cmp_data(odp_packet_t pkt, uint32_t offset, + const void *s, uint32_t len) +{ + const uint8_t *ptr = s; + void *mapaddr; + uint32_t seglen = 0; /* GCC */ + uint32_t cmplen; + int ret; + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + + ODP_ASSERT(offset + len <= pkt_hdr->frame_len); + + while (len > 0) { + mapaddr = packet_map(pkt_hdr, offset, &seglen, NULL); + cmplen = len > seglen ? seglen : len; + ret = memcmp(mapaddr, ptr, cmplen); + if (ret != 0) + return ret; + offset += cmplen; + len -= cmplen; + ptr += cmplen; + } + + return 0; +} + /* * * Debugging @@ -1771,12 +1804,11 @@ static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, uint8_t ihl = _ODP_IPV4HDR_IHL(ipv4->ver_ihl); uint16_t frag_offset; uint32_t dstaddr = odp_be_to_cpu_32(ipv4->dst_addr); - - prs->l3_len = odp_be_to_cpu_16(ipv4->tot_len); + uint32_t l3_len = odp_be_to_cpu_16(ipv4->tot_len); if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN) || odp_unlikely(ver != 4) || - (prs->l3_len > frame_len - *offset)) { + (l3_len > frame_len - *offset)) { prs->error_flags.ip_err = 1; return 0; } @@ -1813,13 +1845,12 @@ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr; const _odp_ipv6hdr_ext_t *ipv6ext; uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr.u8[0]); - - prs->l3_len = odp_be_to_cpu_16(ipv6->payload_len) + - _ODP_IPV6HDR_LEN; + uint32_t l3_len = odp_be_to_cpu_16(ipv6->payload_len) + + _ODP_IPV6HDR_LEN; /* Basic sanity checks on IPv6 header */ if ((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || - prs->l3_len > frame_len - *offset) { + l3_len > frame_len - *offset) { prs->error_flags.ip_err = 1; return 0; } @@ -1880,9 +1911,6 @@ static inline void parse_tcp(packet_parser_t *prs, else if ((uint32_t)tcp->hl * 4 > sizeof(_odp_tcphdr_t)) prs->input_flags.tcpopt = 1; - prs->l4_len = prs->l3_len + - prs->l3_offset - prs->l4_offset; - if (offset) *offset += (uint32_t)tcp->hl * 4; *parseptr += (uint32_t)tcp->hl * 4; @@ -1897,13 +1925,8 @@ static inline void parse_udp(packet_parser_t *prs, const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr; uint32_t udplen = odp_be_to_cpu_16(udp->length); - if (udplen < sizeof(_odp_udphdr_t) || - udplen > (prs->l3_len + - prs->l4_offset - prs->l3_offset)) { + if (odp_unlikely(udplen < sizeof(_odp_udphdr_t))) prs->error_flags.udp_err = 1; - } - - prs->l4_len = udplen; if (offset) *offset += sizeof(_odp_udphdr_t); @@ -1911,215 +1934,170 @@ static inline void parse_udp(packet_parser_t *prs, } /** - * Initialize L2 related parser flags and metadata - */ -void packet_parse_l2(packet_parser_t *prs, uint32_t frame_len) -{ - /* Packet alloc or reset have already init other offsets and flags */ - - /* We only support Ethernet for now */ - prs->input_flags.eth = 1; - - /* Detect jumbo frames */ - if (frame_len > _ODP_ETH_LEN_MAX) - prs->input_flags.jumbo = 1; - - /* Assume valid L2 header, no CRC/FCS check in SW */ - prs->input_flags.l2 = 1; - - prs->input_flags.parsed_l2 = 1; -} - -/** * Parse common packet headers up to given layer * * The function expects at least PACKET_PARSE_SEG_LEN bytes of data to be * available from the ptr. */ int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, - uint32_t frame_len, uint32_t seg_len, layer_t layer) + uint32_t frame_len, uint32_t seg_len, + odp_pktio_parser_layer_t layer) { uint32_t offset; + uint16_t ethtype; const uint8_t *parseptr; + uint8_t ip_proto; + const _odp_ethhdr_t *eth; + uint16_t macaddr0, macaddr2, macaddr4; + const _odp_vlanhdr_t *vlan; - switch (prs->parsed_layers) { - case LAYER_NONE: - /* Fall through */ - - case LAYER_L2: - { - const _odp_ethhdr_t *eth; - uint16_t macaddr0, macaddr2, macaddr4; - const _odp_vlanhdr_t *vlan; - - offset = sizeof(_odp_ethhdr_t); - if (packet_parse_l2_not_done(prs)) - packet_parse_l2(prs, frame_len); - - eth = (const _odp_ethhdr_t *)ptr; - - /* Handle Ethernet broadcast/multicast addresses */ - macaddr0 = odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth)); - prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; - - if (macaddr0 == 0xffff) { - macaddr2 = - odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth + 1)); - macaddr4 = - odp_be_to_cpu_16(*((const uint16_t *) - (const void *)eth + 2)); - prs->input_flags.eth_bcast = - (macaddr2 == 0xffff) && (macaddr4 == 0xffff); - } else { - prs->input_flags.eth_bcast = 0; - } + if (layer == ODP_PKTIO_PARSER_LAYER_NONE) + return 0; - /* Get Ethertype */ - prs->ethtype = odp_be_to_cpu_16(eth->type); - parseptr = (const uint8_t *)(eth + 1); + /* We only support Ethernet for now */ + prs->input_flags.eth = 1; + /* Assume valid L2 header, no CRC/FCS check in SW */ + prs->input_flags.l2 = 1; + /* Detect jumbo frames */ + if (frame_len > _ODP_ETH_LEN_MAX) + prs->input_flags.jumbo = 1; - /* Check for SNAP vs. DIX */ - if (prs->ethtype < _ODP_ETH_LEN_MAX) { - prs->input_flags.snap = 1; - if (prs->ethtype > frame_len - offset) { - prs->error_flags.snap_len = 1; - goto parse_exit; - } - prs->ethtype = odp_be_to_cpu_16(*((const uint16_t *) - (uintptr_t) - (parseptr + 6))); - offset += 8; - parseptr += 8; - } + offset = sizeof(_odp_ethhdr_t); + eth = (const _odp_ethhdr_t *)ptr; + + /* Handle Ethernet broadcast/multicast addresses */ + macaddr0 = odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth)); + prs->input_flags.eth_mcast = (macaddr0 & 0x0100) == 0x0100; + + if (macaddr0 == 0xffff) { + macaddr2 = + odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 1)); + macaddr4 = + odp_be_to_cpu_16(*((const uint16_t *) + (const void *)eth + 2)); + prs->input_flags.eth_bcast = + (macaddr2 == 0xffff) && (macaddr4 == 0xffff); + } else { + prs->input_flags.eth_bcast = 0; + } - /* Parse the VLAN header(s), if present */ - if (prs->ethtype == _ODP_ETHTYPE_VLAN_OUTER) { - prs->input_flags.vlan_qinq = 1; - prs->input_flags.vlan = 1; + /* Get Ethertype */ + ethtype = odp_be_to_cpu_16(eth->type); + parseptr = (const uint8_t *)(eth + 1); - vlan = (const _odp_vlanhdr_t *)parseptr; - prs->ethtype = odp_be_to_cpu_16(vlan->type); - offset += sizeof(_odp_vlanhdr_t); - parseptr += sizeof(_odp_vlanhdr_t); + /* Check for SNAP vs. DIX */ + if (ethtype < _ODP_ETH_LEN_MAX) { + prs->input_flags.snap = 1; + if (ethtype > frame_len - offset) { + prs->error_flags.snap_len = 1; + goto parse_exit; } + ethtype = odp_be_to_cpu_16(*((const uint16_t *)(uintptr_t) + (parseptr + 6))); + offset += 8; + parseptr += 8; + } - if (prs->ethtype == _ODP_ETHTYPE_VLAN) { - prs->input_flags.vlan = 1; - vlan = (const _odp_vlanhdr_t *)parseptr; - prs->ethtype = odp_be_to_cpu_16(vlan->type); - offset += sizeof(_odp_vlanhdr_t); - parseptr += sizeof(_odp_vlanhdr_t); - } + /* Parse the VLAN header(s), if present */ + if (ethtype == _ODP_ETHTYPE_VLAN_OUTER) { + prs->input_flags.vlan_qinq = 1; + prs->input_flags.vlan = 1; - prs->l3_offset = offset; - prs->parsed_layers = LAYER_L2; - if (layer == LAYER_L2) - return prs->error_flags.all != 0; + vlan = (const _odp_vlanhdr_t *)parseptr; + ethtype = odp_be_to_cpu_16(vlan->type); + offset += sizeof(_odp_vlanhdr_t); + parseptr += sizeof(_odp_vlanhdr_t); } - /* Fall through */ - case LAYER_L3: - { - offset = prs->l3_offset; - parseptr = (const uint8_t *)(ptr + offset); - /* Set l3_offset+flag only for known ethtypes */ - prs->input_flags.l3 = 1; - - /* Parse Layer 3 headers */ - switch (prs->ethtype) { - case _ODP_ETHTYPE_IPV4: - prs->input_flags.ipv4 = 1; - prs->ip_proto = parse_ipv4(prs, &parseptr, &offset, - frame_len); - break; + if (ethtype == _ODP_ETHTYPE_VLAN) { + prs->input_flags.vlan = 1; + vlan = (const _odp_vlanhdr_t *)parseptr; + ethtype = odp_be_to_cpu_16(vlan->type); + offset += sizeof(_odp_vlanhdr_t); + parseptr += sizeof(_odp_vlanhdr_t); + } - case _ODP_ETHTYPE_IPV6: - prs->input_flags.ipv6 = 1; - prs->ip_proto = parse_ipv6(prs, &parseptr, &offset, - frame_len, seg_len); - break; + if (layer == ODP_PKTIO_PARSER_LAYER_L2) + return prs->error_flags.all != 0; - case _ODP_ETHTYPE_ARP: - prs->input_flags.arp = 1; - prs->ip_proto = 255; /* Reserved invalid by IANA */ - break; + /* Set l3_offset+flag only for known ethtypes */ + prs->l3_offset = offset; + prs->input_flags.l3 = 1; - default: - prs->input_flags.l3 = 0; - prs->l3_offset = ODP_PACKET_OFFSET_INVALID; - prs->ip_proto = 255; /* Reserved invalid by IANA */ - } + /* Parse Layer 3 headers */ + switch (ethtype) { + case _ODP_ETHTYPE_IPV4: + prs->input_flags.ipv4 = 1; + ip_proto = parse_ipv4(prs, &parseptr, &offset, frame_len); + break; - /* Set l4_offset+flag only for known ip_proto */ - prs->l4_offset = offset; - prs->parsed_layers = LAYER_L3; - if (layer == LAYER_L3) - return prs->error_flags.all != 0; - } - /* Fall through */ + case _ODP_ETHTYPE_IPV6: + prs->input_flags.ipv6 = 1; + ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, + seg_len); + break; - case LAYER_L4: - { - offset = prs->l4_offset; - parseptr = (const uint8_t *)(ptr + offset); - prs->input_flags.l4 = 1; + case _ODP_ETHTYPE_ARP: + prs->input_flags.arp = 1; + ip_proto = 255; /* Reserved invalid by IANA */ + break; - /* Parse Layer 4 headers */ - switch (prs->ip_proto) { - case _ODP_IPPROTO_ICMP: - prs->input_flags.icmp = 1; - break; + default: + prs->input_flags.l3 = 0; + prs->l3_offset = ODP_PACKET_OFFSET_INVALID; + ip_proto = 255; /* Reserved invalid by IANA */ + } - case _ODP_IPPROTO_TCP: - if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) - return -1; - prs->input_flags.tcp = 1; - parse_tcp(prs, &parseptr, NULL); - break; + if (layer == ODP_PKTIO_PARSER_LAYER_L3) + return prs->error_flags.all != 0; - case _ODP_IPPROTO_UDP: - if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) - return -1; - prs->input_flags.udp = 1; - parse_udp(prs, &parseptr, NULL); - break; + /* Set l4_offset+flag only for known ip_proto */ + prs->l4_offset = offset; + prs->input_flags.l4 = 1; - case _ODP_IPPROTO_AH: - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_ah = 1; - break; + /* Parse Layer 4 headers */ + switch (ip_proto) { + case _ODP_IPPROTO_ICMPv4: + /* Fall through */ - case _ODP_IPPROTO_ESP: - prs->input_flags.ipsec = 1; - prs->input_flags.ipsec_esp = 1; - break; + case _ODP_IPPROTO_ICMPv6: + prs->input_flags.icmp = 1; + break; - case _ODP_IPPROTO_SCTP: - prs->input_flags.sctp = 1; - break; + case _ODP_IPPROTO_TCP: + if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len)) + return -1; + prs->input_flags.tcp = 1; + parse_tcp(prs, &parseptr, NULL); + break; - default: - prs->input_flags.l4 = 0; - prs->l4_offset = ODP_PACKET_OFFSET_INVALID; - break; - } + case _ODP_IPPROTO_UDP: + if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) + return -1; + prs->input_flags.udp = 1; + parse_udp(prs, &parseptr, NULL); + break; - prs->parsed_layers = LAYER_L4; + case _ODP_IPPROTO_AH: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_ah = 1; + break; + + case _ODP_IPPROTO_ESP: + prs->input_flags.ipsec = 1; + prs->input_flags.ipsec_esp = 1; break; - } - case LAYER_ALL: + case _ODP_IPPROTO_SCTP: + prs->input_flags.sctp = 1; break; default: - ODP_ERR("Invalid parse layer: %d\n", (int)layer); - return -1; + prs->input_flags.l4 = 0; + prs->l4_offset = ODP_PACKET_OFFSET_INVALID; + break; } - - prs->parsed_layers = LAYER_ALL; - parse_exit: return prs->error_flags.all != 0; } @@ -2127,7 +2105,8 @@ parse_exit: /** * Simple packet parser */ -int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, layer_t layer) +int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, + odp_pktio_parser_layer_t layer) { uint32_t seg_len = packet_first_seg_len(pkt_hdr); void *base = packet_data(pkt_hdr); diff --git a/platform/linux-generic/odp_packet_flags.c b/platform/linux-generic/odp_packet_flags.c index ea9a22710..72df1ecfe 100644 --- a/platform/linux-generic/odp_packet_flags.c +++ b/platform/linux-generic/odp_packet_flags.c @@ -8,27 +8,21 @@ #include <odp/api/packet_flags.h> #include <odp_packet_internal.h> -#define retflag(pkt, x, layer) do { \ +#define retflag(pkt, x) do { \ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); \ - if (pkt_hdr->p.parsed_layers < layer) \ - packet_parse_layer(pkt_hdr, layer); \ return pkt_hdr->p.x; \ } while (0) -#define setflag(pkt, x, v, layer) do { \ +#define setflag(pkt, x, v) do { \ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); \ - if (pkt_hdr->p.parsed_layers < layer) \ - packet_parse_layer(pkt_hdr, layer); \ - pkt_hdr->p.x = v & 1; \ + pkt_hdr->p.x = (v) & 1; \ } while (0) int odp_packet_has_error(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - return odp_packet_hdr(pkt)->p.error_flags.all != 0; + return pkt_hdr->p.error_flags.all != 0; } /* Get Input Flags */ @@ -45,126 +39,117 @@ int odp_packet_has_l2_error(odp_packet_t pkt) int odp_packet_has_l3(odp_packet_t pkt) { - retflag(pkt, input_flags.l3, LAYER_L3); + retflag(pkt, input_flags.l3); } int odp_packet_has_l3_error(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L3) - packet_parse_layer(pkt_hdr, LAYER_L3); - return pkt_hdr->p.error_flags.ip_err; } int odp_packet_has_l4(odp_packet_t pkt) { - retflag(pkt, input_flags.l4, LAYER_L4); + retflag(pkt, input_flags.l4); } int odp_packet_has_l4_error(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (pkt_hdr->p.parsed_layers < LAYER_L4) - packet_parse_layer(pkt_hdr, LAYER_L4); - return pkt_hdr->p.error_flags.tcp_err | pkt_hdr->p.error_flags.udp_err; } int odp_packet_has_eth_bcast(odp_packet_t pkt) { - retflag(pkt, input_flags.eth_bcast, LAYER_L2); + retflag(pkt, input_flags.eth_bcast); } int odp_packet_has_eth_mcast(odp_packet_t pkt) { - retflag(pkt, input_flags.eth_mcast, LAYER_L2); + retflag(pkt, input_flags.eth_mcast); } int odp_packet_has_vlan(odp_packet_t pkt) { - retflag(pkt, input_flags.vlan, LAYER_L2); + retflag(pkt, input_flags.vlan); } int odp_packet_has_vlan_qinq(odp_packet_t pkt) { - retflag(pkt, input_flags.vlan_qinq, LAYER_L2); + retflag(pkt, input_flags.vlan_qinq); } int odp_packet_has_arp(odp_packet_t pkt) { - retflag(pkt, input_flags.arp, LAYER_L3); + retflag(pkt, input_flags.arp); } int odp_packet_has_ipv4(odp_packet_t pkt) { - retflag(pkt, input_flags.ipv4, LAYER_L3); + retflag(pkt, input_flags.ipv4); } int odp_packet_has_ipv6(odp_packet_t pkt) { - retflag(pkt, input_flags.ipv6, LAYER_L3); + retflag(pkt, input_flags.ipv6); } int odp_packet_has_ip_bcast(odp_packet_t pkt) { - retflag(pkt, input_flags.ip_bcast, LAYER_L3); + retflag(pkt, input_flags.ip_bcast); } int odp_packet_has_ip_mcast(odp_packet_t pkt) { - retflag(pkt, input_flags.ip_mcast, LAYER_L3); + retflag(pkt, input_flags.ip_mcast); } int odp_packet_has_ipfrag(odp_packet_t pkt) { - retflag(pkt, input_flags.ipfrag, LAYER_L3); + retflag(pkt, input_flags.ipfrag); } int odp_packet_has_ipopt(odp_packet_t pkt) { - retflag(pkt, input_flags.ipopt, LAYER_L3); + retflag(pkt, input_flags.ipopt); } int odp_packet_has_ipsec(odp_packet_t pkt) { - retflag(pkt, input_flags.ipsec, LAYER_L4); + retflag(pkt, input_flags.ipsec); } int odp_packet_has_udp(odp_packet_t pkt) { - retflag(pkt, input_flags.udp, LAYER_L4); + retflag(pkt, input_flags.udp); } int odp_packet_has_tcp(odp_packet_t pkt) { - retflag(pkt, input_flags.tcp, LAYER_L4); + retflag(pkt, input_flags.tcp); } int odp_packet_has_sctp(odp_packet_t pkt) { - retflag(pkt, input_flags.sctp, LAYER_L4); + retflag(pkt, input_flags.sctp); } int odp_packet_has_icmp(odp_packet_t pkt) { - retflag(pkt, input_flags.icmp, LAYER_L4); + retflag(pkt, input_flags.icmp); } odp_packet_color_t odp_packet_color(odp_packet_t pkt) { - retflag(pkt, input_flags.color, LAYER_ALL); + retflag(pkt, input_flags.color); } void odp_packet_color_set(odp_packet_t pkt, odp_packet_color_t color) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - pkt_hdr->p.input_flags.color = color; } @@ -172,29 +157,23 @@ odp_bool_t odp_packet_drop_eligible(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - return !pkt_hdr->p.input_flags.nodrop; } void odp_packet_drop_eligible_set(odp_packet_t pkt, odp_bool_t drop) { - setflag(pkt, input_flags.nodrop, !drop, LAYER_ALL); + setflag(pkt, input_flags.nodrop, !drop); } int8_t odp_packet_shaper_len_adjust(odp_packet_t pkt) { - retflag(pkt, output_flags.shaper_len_adj, LAYER_ALL); + retflag(pkt, output_flags.shaper_len_adj); } void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj) { odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); - if (packet_parse_not_complete(pkt_hdr)) - packet_parse_layer(pkt_hdr, LAYER_ALL); - pkt_hdr->p.output_flags.shaper_len_adj = adj; } @@ -202,107 +181,107 @@ void odp_packet_shaper_len_adjust_set(odp_packet_t pkt, int8_t adj) void odp_packet_has_l2_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.l2, val, LAYER_L2); + setflag(pkt, input_flags.l2, val); } void odp_packet_has_l3_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.l3, val, LAYER_L3); + setflag(pkt, input_flags.l3, val); } void odp_packet_has_l4_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.l4, val, LAYER_L4); + setflag(pkt, input_flags.l4, val); } void odp_packet_has_eth_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.eth, val, LAYER_L2); + setflag(pkt, input_flags.eth, val); } void odp_packet_has_eth_bcast_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.eth_bcast, val, LAYER_L2); + setflag(pkt, input_flags.eth_bcast, val); } void odp_packet_has_eth_mcast_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.eth_mcast, val, LAYER_L2); + setflag(pkt, input_flags.eth_mcast, val); } void odp_packet_has_jumbo_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.jumbo, val, LAYER_L2); + setflag(pkt, input_flags.jumbo, val); } void odp_packet_has_vlan_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.vlan, val, LAYER_L2); + setflag(pkt, input_flags.vlan, val); } void odp_packet_has_vlan_qinq_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.vlan_qinq, val, LAYER_L2); + setflag(pkt, input_flags.vlan_qinq, val); } void odp_packet_has_arp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.arp, val, LAYER_L3); + setflag(pkt, input_flags.arp, val); } void odp_packet_has_ipv4_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipv4, val, LAYER_L3); + setflag(pkt, input_flags.ipv4, val); } void odp_packet_has_ipv6_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipv6, val, LAYER_L3); + setflag(pkt, input_flags.ipv6, val); } void odp_packet_has_ip_bcast_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ip_bcast, val, LAYER_L3); + setflag(pkt, input_flags.ip_bcast, val); } void odp_packet_has_ip_mcast_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ip_mcast, val, LAYER_L3); + setflag(pkt, input_flags.ip_mcast, val); } void odp_packet_has_ipfrag_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipfrag, val, LAYER_L3); + setflag(pkt, input_flags.ipfrag, val); } void odp_packet_has_ipopt_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipopt, val, LAYER_L3); + setflag(pkt, input_flags.ipopt, val); } void odp_packet_has_ipsec_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.ipsec, val, LAYER_L4); + setflag(pkt, input_flags.ipsec, val); } void odp_packet_has_udp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.udp, val, LAYER_L4); + setflag(pkt, input_flags.udp, val); } void odp_packet_has_tcp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.tcp, val, LAYER_L4); + setflag(pkt, input_flags.tcp, val); } void odp_packet_has_sctp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.sctp, val, LAYER_L4); + setflag(pkt, input_flags.sctp, val); } void odp_packet_has_icmp_set(odp_packet_t pkt, int val) { - setflag(pkt, input_flags.icmp, val, LAYER_L4); + setflag(pkt, input_flags.icmp, val); } void odp_packet_has_flow_hash_clr(odp_packet_t pkt) diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index 98460a566..877978ba2 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -206,6 +206,8 @@ static odp_pktio_t setup_pktio_entry(const char *name, odp_pool_t pool, memcpy(&pktio_entry->s.param, param, sizeof(odp_pktio_param_t)); pktio_entry->s.handle = hdl; + odp_pktio_config_init(&pktio_entry->s.config); + for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) { ret = pktio_if_ops[pktio_if]->open(hdl, pktio_entry, name, pool); @@ -586,6 +588,10 @@ int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr) int len = 1; int nbr; + if (sched_fn->ord_enq_multi(qentry->s.index, (void **)buf_hdr, len, + &nbr)) + return (nbr == len ? 0 : -1); + nbr = odp_pktout_send(qentry->s.pktout, &pkt, len); return (nbr == len ? 0 : -1); } @@ -603,6 +609,10 @@ int pktout_enq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int nbr; int i; + if (sched_fn->ord_enq_multi(qentry->s.index, (void **)buf_hdr, num, + &nbr)) + return nbr; + for (i = 0; i < num; ++i) pkt_tbl[i] = _odp_packet_from_buffer(buf_hdr[i]->handle.handle); @@ -923,6 +933,8 @@ void odp_pktout_queue_param_init(odp_pktout_queue_param_t *param) void odp_pktio_config_init(odp_pktio_config_t *config) { memset(config, 0, sizeof(odp_pktio_config_t)); + + config->parser.layer = ODP_PKTIO_PARSER_LAYER_ALL; } int odp_pktio_info(odp_pktio_t hdl, odp_pktio_info_t *info) @@ -1098,6 +1110,7 @@ int odp_pktio_term_global(void) int odp_pktio_capability(odp_pktio_t pktio, odp_pktio_capability_t *capa) { pktio_entry_t *entry; + int ret; entry = get_pktio_entry(pktio); if (entry == NULL) { @@ -1106,9 +1119,15 @@ int odp_pktio_capability(odp_pktio_t pktio, odp_pktio_capability_t *capa) } if (entry->s.ops->capability) - return entry->s.ops->capability(entry, capa); + ret = entry->s.ops->capability(entry, capa); + else + ret = single_capability(capa); - return single_capability(capa); + /* The same parser is used for all pktios */ + if (ret == 0) + capa->config.parser.layer = ODP_PKTIO_PARSER_LAYER_ALL; + + return ret; } unsigned odp_pktio_max_index(void) diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c index cf7c2c415..9dba73413 100644 --- a/platform/linux-generic/odp_pool.c +++ b/platform/linux-generic/odp_pool.c @@ -445,7 +445,8 @@ static int check_params(odp_pool_param_t *params) { odp_pool_capability_t capa; - odp_pool_capability(&capa); + if (odp_pool_capability(&capa) < 0) + return -1; switch (params->type) { case ODP_POOL_BUFFER: @@ -768,6 +769,8 @@ odp_buffer_t odp_buffer_alloc(odp_pool_t pool_hdl) pool_t *pool; int ret; + ODP_ASSERT(ODP_POOL_INVALID != pool_hdl); + pool = pool_entry_from_hdl(pool_hdl); ret = buffer_alloc_multi(pool, &buf, NULL, 1); @@ -781,6 +784,8 @@ int odp_buffer_alloc_multi(odp_pool_t pool_hdl, odp_buffer_t buf[], int num) { pool_t *pool; + ODP_ASSERT(ODP_POOL_INVALID != pool_hdl); + pool = pool_entry_from_hdl(pool_hdl); return buffer_alloc_multi(pool, buf, NULL, num); diff --git a/platform/linux-generic/odp_queue.c b/platform/linux-generic/odp_queue.c index d4267c72f..450613394 100644 --- a/platform/linux-generic/odp_queue.c +++ b/platform/linux-generic/odp_queue.c @@ -95,6 +95,7 @@ static int queue_init(queue_entry_t *queue, const char *name, queue->s.dequeue_multi = queue_deq_multi; queue->s.pktin = PKTIN_INVALID; + queue->s.pktout = PKTOUT_INVALID; queue->s.head = NULL; queue->s.tail = NULL; @@ -175,6 +176,8 @@ int odp_queue_capability(odp_queue_capability_t *capa) capa->max_ordered_locks = sched_fn->max_ordered_locks(); capa->max_sched_groups = sched_fn->num_grps(); capa->sched_prios = odp_schedule_num_prio(); + capa->plain.max_num = capa->max_queues; + capa->sched.max_num = capa->max_queues; return 0; } diff --git a/platform/linux-generic/odp_rwlock.c b/platform/linux-generic/odp_rwlock.c index 13c17a2c7..5bef13a45 100644 --- a/platform/linux-generic/odp_rwlock.c +++ b/platform/linux-generic/odp_rwlock.c @@ -33,9 +33,14 @@ void odp_rwlock_read_lock(odp_rwlock_t *rwlock) int odp_rwlock_read_trylock(odp_rwlock_t *rwlock) { - uint32_t zero = 0; + uint32_t cnt = odp_atomic_load_u32(&rwlock->cnt); + + while (cnt != (uint32_t)-1) { + if (odp_atomic_cas_acq_u32(&rwlock->cnt, &cnt, cnt + 1)) + return 1; + } - return odp_atomic_cas_acq_u32(&rwlock->cnt, &zero, (uint32_t)1); + return 0; } void odp_rwlock_read_unlock(odp_rwlock_t *rwlock) diff --git a/platform/linux-generic/odp_schedule.c b/platform/linux-generic/odp_schedule.c index cd5bf21bd..c4567d810 100644 --- a/platform/linux-generic/odp_schedule.c +++ b/platform/linux-generic/odp_schedule.c @@ -20,6 +20,7 @@ #include <odp_config_internal.h> #include <odp_align_internal.h> #include <odp/api/sync.h> +#include <odp/api/packet_io.h> #include <odp_ring_internal.h> #include <odp_queue_internal.h> @@ -34,11 +35,18 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) && "normal_prio_is_not_between_highest_and_lowest"); /* Number of scheduling groups */ -#define NUM_SCHED_GRPS 256 +#define NUM_SCHED_GRPS 32 /* Priority queues per priority */ #define QUEUES_PER_PRIO 4 +/* A thread polls a non preferred sched queue every this many polls + * of the prefer queue. */ +#define PREFER_RATIO 64 + +/* Size of poll weight table */ +#define WEIGHT_TBL_SIZE ((QUEUES_PER_PRIO - 1) * PREFER_RATIO) + /* Packet input poll cmd queues */ #define PKTIO_CMD_QUEUES 4 @@ -142,7 +150,6 @@ typedef struct { int index; int pause; uint16_t round; - uint16_t prefer_offset; uint16_t pktin_polls; uint32_t queue_index; odp_queue_t queue; @@ -157,6 +164,12 @@ typedef struct { ordered_stash_t stash[MAX_ORDERED_STASH]; } ordered; + uint32_t grp_epoch; + int num_grp; + uint8_t grp[NUM_SCHED_GRPS]; + uint8_t weight_tbl[WEIGHT_TBL_SIZE]; + uint8_t grp_weight[WEIGHT_TBL_SIZE]; + } sched_local_t; /* Priority queue */ @@ -191,7 +204,7 @@ typedef struct { pri_mask_t pri_mask[NUM_PRIO]; odp_spinlock_t mask_lock; - prio_queue_t prio_q[NUM_PRIO][QUEUES_PER_PRIO]; + prio_queue_t prio_q[NUM_SCHED_GRPS][NUM_PRIO][QUEUES_PER_PRIO]; odp_spinlock_t poll_cmd_lock; /* Number of commands in a command queue */ @@ -206,8 +219,10 @@ typedef struct { odp_shm_t shm; uint32_t pri_count[NUM_PRIO][QUEUES_PER_PRIO]; - odp_spinlock_t grp_lock; - odp_thrmask_t mask_all; + odp_thrmask_t mask_all; + odp_spinlock_t grp_lock; + odp_atomic_u32_t grp_epoch; + struct { char name[ODP_SCHED_GROUP_NAME_LEN]; odp_thrmask_t mask; @@ -215,6 +230,7 @@ typedef struct { } sched_grp[NUM_SCHED_GRPS]; struct { + int grp; int prio; int queue_per_prio; } queue[ODP_CONFIG_QUEUES]; @@ -237,17 +253,35 @@ static inline void schedule_release_context(void); static void sched_local_init(void) { + int i; + uint8_t id; + uint8_t offset = 0; + memset(&sched_local, 0, sizeof(sched_local_t)); sched_local.thr = odp_thread_id(); sched_local.queue = ODP_QUEUE_INVALID; sched_local.queue_index = PRIO_QUEUE_EMPTY; + + id = sched_local.thr & (QUEUES_PER_PRIO - 1); + + for (i = 0; i < WEIGHT_TBL_SIZE; i++) { + sched_local.weight_tbl[i] = id; + + if (i % PREFER_RATIO == 0) { + offset++; + sched_local.weight_tbl[i] = (id + offset) & + (QUEUES_PER_PRIO - 1); + if (offset == QUEUES_PER_PRIO - 1) + offset = 0; + } + } } static int schedule_init_global(void) { odp_shm_t shm; - int i, j; + int i, j, grp; ODP_DBG("Schedule init ... "); @@ -267,15 +301,20 @@ static int schedule_init_global(void) sched->shm = shm; odp_spinlock_init(&sched->mask_lock); - for (i = 0; i < NUM_PRIO; i++) { - for (j = 0; j < QUEUES_PER_PRIO; j++) { - int k; + for (grp = 0; grp < NUM_SCHED_GRPS; grp++) { + for (i = 0; i < NUM_PRIO; i++) { + for (j = 0; j < QUEUES_PER_PRIO; j++) { + prio_queue_t *prio_q; + int k; - ring_init(&sched->prio_q[i][j].ring); + prio_q = &sched->prio_q[grp][i][j]; + ring_init(&prio_q->ring); - for (k = 0; k < PRIO_QUEUE_RING_SIZE; k++) - sched->prio_q[i][j].queue_index[k] = - PRIO_QUEUE_EMPTY; + for (k = 0; k < PRIO_QUEUE_RING_SIZE; k++) { + prio_q->queue_index[k] = + PRIO_QUEUE_EMPTY; + } + } } } @@ -291,12 +330,17 @@ static int schedule_init_global(void) sched->pktio_cmd[i].cmd_index = PKTIO_CMD_FREE; odp_spinlock_init(&sched->grp_lock); + odp_atomic_init_u32(&sched->grp_epoch, 0); for (i = 0; i < NUM_SCHED_GRPS; i++) { memset(sched->sched_grp[i].name, 0, ODP_SCHED_GROUP_NAME_LEN); odp_thrmask_zero(&sched->sched_grp[i].mask); } + sched->sched_grp[ODP_SCHED_GROUP_ALL].allocated = 1; + sched->sched_grp[ODP_SCHED_GROUP_WORKER].allocated = 1; + sched->sched_grp[ODP_SCHED_GROUP_CONTROL].allocated = 1; + odp_thrmask_setall(&sched->mask_all); ODP_DBG("done\n"); @@ -304,29 +348,38 @@ static int schedule_init_global(void) return 0; } +static inline void queue_destroy_finalize(uint32_t qi) +{ + sched_cb_queue_destroy_finalize(qi); +} + static int schedule_term_global(void) { int ret = 0; int rc = 0; - int i, j; + int i, j, grp; - for (i = 0; i < NUM_PRIO; i++) { - for (j = 0; j < QUEUES_PER_PRIO; j++) { - ring_t *ring = &sched->prio_q[i][j].ring; - uint32_t qi; + for (grp = 0; grp < NUM_SCHED_GRPS; grp++) { + for (i = 0; i < NUM_PRIO; i++) { + for (j = 0; j < QUEUES_PER_PRIO; j++) { + ring_t *ring = &sched->prio_q[grp][i][j].ring; + uint32_t qi; - while ((qi = ring_deq(ring, PRIO_QUEUE_MASK)) != - RING_EMPTY) { - odp_event_t events[1]; - int num; + while ((qi = ring_deq(ring, PRIO_QUEUE_MASK)) != + RING_EMPTY) { + odp_event_t events[1]; + int num; - num = sched_cb_queue_deq_multi(qi, events, 1); + num = sched_cb_queue_deq_multi(qi, + events, + 1); - if (num < 0) - sched_cb_queue_destroy_finalize(qi); + if (num < 0) + queue_destroy_finalize(qi); - if (num > 0) - ODP_ERR("Queue not empty\n"); + if (num > 0) + ODP_ERR("Queue not empty\n"); + } } } } @@ -357,6 +410,40 @@ static int schedule_term_local(void) return 0; } +static inline void grp_update_mask(int grp, const odp_thrmask_t *new_mask) +{ + odp_thrmask_copy(&sched->sched_grp[grp].mask, new_mask); + odp_atomic_add_rel_u32(&sched->grp_epoch, 1); +} + +static inline int grp_update_tbl(void) +{ + int i; + int num = 0; + int thr = sched_local.thr; + + odp_spinlock_lock(&sched->grp_lock); + + for (i = 0; i < NUM_SCHED_GRPS; i++) { + if (sched->sched_grp[i].allocated == 0) + continue; + + if (odp_thrmask_isset(&sched->sched_grp[i].mask, thr)) { + sched_local.grp[num] = i; + num++; + } + } + + odp_spinlock_unlock(&sched->grp_lock); + + /* Update group weights. Round robin over all thread's groups. */ + for (i = 0; i < WEIGHT_TBL_SIZE; i++) + sched_local.grp_weight[i] = i % num; + + sched_local.num_grp = num; + return num; +} + static unsigned schedule_max_ordered_locks(void) { return MAX_ORDERED_LOCKS_PER_QUEUE; @@ -407,6 +494,7 @@ static int schedule_init_queue(uint32_t queue_index, int prio = sched_param->prio; pri_set_queue(queue_index, prio); + sched->queue[queue_index].grp = sched_param->group; sched->queue[queue_index].prio = prio; sched->queue[queue_index].queue_per_prio = queue_per_prio(queue_index); @@ -418,6 +506,7 @@ static void schedule_destroy_queue(uint32_t queue_index) int prio = sched->queue[queue_index].prio; pri_clr_queue(queue_index, prio); + sched->queue[queue_index].grp = 0; sched->queue[queue_index].prio = 0; sched->queue[queue_index].queue_per_prio = 0; } @@ -509,9 +598,10 @@ static void schedule_release_atomic(void) uint32_t qi = sched_local.queue_index; if (qi != PRIO_QUEUE_EMPTY && sched_local.num == 0) { - int prio = sched->queue[qi].prio; + int grp = sched->queue[qi].grp; + int prio = sched->queue[qi].prio; int queue_per_prio = sched->queue[qi].queue_per_prio; - ring_t *ring = &sched->prio_q[prio][queue_per_prio].ring; + ring_t *ring = &sched->prio_q[grp][prio][queue_per_prio].ring; /* Release current atomic queue */ ring_enq(ring, PRIO_QUEUE_MASK, qi); @@ -640,7 +730,9 @@ static int schedule_ord_enq_multi(uint32_t queue_index, void *buf_hdr[], return 0; } - if (odp_unlikely(stash_num >= MAX_ORDERED_STASH)) { + /* Pktout may drop packets, so the operation cannot be stashed. */ + if (dst_queue->s.pktout.pktio != ODP_PKTIO_INVALID || + odp_unlikely(stash_num >= MAX_ORDERED_STASH)) { /* If the local stash is full, wait until it is our turn and * then release the stash and do enqueue directly. */ wait_for_order(src_queue); @@ -662,54 +754,26 @@ static int schedule_ord_enq_multi(uint32_t queue_index, void *buf_hdr[], return 1; } -/* - * Schedule queues - */ -static int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], - unsigned int max_num) +static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], + unsigned int max_num, int grp, int first) { int prio, i; int ret; int id; - int offset = 0; unsigned int max_deq = MAX_DEQ; uint32_t qi; - if (sched_local.num) { - ret = copy_events(out_ev, max_num); - - if (out_queue) - *out_queue = sched_local.queue; - - return ret; - } - - schedule_release_context(); - - if (odp_unlikely(sched_local.pause)) - return 0; - - /* Each thread prefers a priority queue. This offset avoids starvation - * of other priority queues on low thread counts. */ - if (odp_unlikely((sched_local.round & 0x3f) == 0)) { - offset = sched_local.prefer_offset; - sched_local.prefer_offset = (offset + 1) & - (QUEUES_PER_PRIO - 1); - } - - sched_local.round++; - /* Schedule events */ for (prio = 0; prio < NUM_PRIO; prio++) { if (sched->pri_mask[prio] == 0) continue; - id = (sched_local.thr + offset) & (QUEUES_PER_PRIO - 1); + /* Select the first ring based on weights */ + id = first; for (i = 0; i < QUEUES_PER_PRIO;) { int num; - int grp; int ordered; odp_queue_t handle; ring_t *ring; @@ -726,7 +790,7 @@ static int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], } /* Get queue index from the priority queue */ - ring = &sched->prio_q[prio][id].ring; + ring = &sched->prio_q[grp][prio][id].ring; qi = ring_deq(ring, PRIO_QUEUE_MASK); /* Priority queue empty */ @@ -736,24 +800,10 @@ static int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], continue; } - grp = sched_cb_queue_grp(qi); - - if (grp > ODP_SCHED_GROUP_ALL && - !odp_thrmask_isset(&sched->sched_grp[grp].mask, - sched_local.thr)) { - /* This thread is not eligible for work from - * this queue, so continue scheduling it. - */ - ring_enq(ring, PRIO_QUEUE_MASK, qi); - - i++; - id++; - continue; - } - /* Low priorities have smaller batch size to limit * head of line blocking latency. */ - if (odp_unlikely(prio > ODP_SCHED_PRIO_DEFAULT)) + if (odp_unlikely(MAX_DEQ > 1 && + prio > ODP_SCHED_PRIO_DEFAULT)) max_deq = MAX_DEQ / 2; ordered = sched_cb_queue_is_ordered(qi); @@ -818,6 +868,70 @@ static int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], } } + return 0; +} + +/* + * Schedule queues + */ +static inline int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], + unsigned int max_num) +{ + int i, num_grp; + int ret; + int id, first, grp_id; + uint16_t round; + uint32_t epoch; + + if (sched_local.num) { + ret = copy_events(out_ev, max_num); + + if (out_queue) + *out_queue = sched_local.queue; + + return ret; + } + + schedule_release_context(); + + if (odp_unlikely(sched_local.pause)) + return 0; + + /* Each thread prefers a priority queue. Poll weight table avoids + * starvation of other priority queues on low thread counts. */ + round = sched_local.round + 1; + + if (odp_unlikely(round == WEIGHT_TBL_SIZE)) + round = 0; + + sched_local.round = round; + first = sched_local.weight_tbl[round]; + + epoch = odp_atomic_load_acq_u32(&sched->grp_epoch); + num_grp = sched_local.num_grp; + + if (odp_unlikely(sched_local.grp_epoch != epoch)) { + num_grp = grp_update_tbl(); + sched_local.grp_epoch = epoch; + } + + grp_id = sched_local.grp_weight[round]; + + /* Schedule queues per group and priority */ + for (i = 0; i < num_grp; i++) { + int grp; + + grp = sched_local.grp[grp_id]; + ret = do_schedule_grp(out_queue, out_ev, max_num, grp, first); + + if (odp_likely(ret)) + return ret; + + grp_id++; + if (odp_unlikely(grp_id >= num_grp)) + grp_id = 0; + } + /* * Poll packet input when there are no events * * Each thread starts the search for a poll command from its @@ -1023,7 +1137,8 @@ static odp_schedule_group_t schedule_group_create(const char *name, ODP_SCHED_GROUP_NAME_LEN - 1); grp_name[ODP_SCHED_GROUP_NAME_LEN - 1] = 0; } - odp_thrmask_copy(&sched->sched_grp[i].mask, mask); + + grp_update_mask(i, mask); group = (odp_schedule_group_t)i; sched->sched_grp[i].allocated = 1; break; @@ -1036,13 +1151,16 @@ static odp_schedule_group_t schedule_group_create(const char *name, static int schedule_group_destroy(odp_schedule_group_t group) { + odp_thrmask_t zero; int ret; + odp_thrmask_zero(&zero); + odp_spinlock_lock(&sched->grp_lock); if (group < NUM_SCHED_GRPS && group >= SCHED_GROUP_NAMED && sched->sched_grp[group].allocated) { - odp_thrmask_zero(&sched->sched_grp[group].mask); + grp_update_mask(group, &zero); memset(sched->sched_grp[group].name, 0, ODP_SCHED_GROUP_NAME_LEN); sched->sched_grp[group].allocated = 0; @@ -1082,9 +1200,11 @@ static int schedule_group_join(odp_schedule_group_t group, if (group < NUM_SCHED_GRPS && group >= SCHED_GROUP_NAMED && sched->sched_grp[group].allocated) { - odp_thrmask_or(&sched->sched_grp[group].mask, - &sched->sched_grp[group].mask, - mask); + odp_thrmask_t new_mask; + + odp_thrmask_or(&new_mask, &sched->sched_grp[group].mask, mask); + grp_update_mask(group, &new_mask); + ret = 0; } else { ret = -1; @@ -1097,18 +1217,19 @@ static int schedule_group_join(odp_schedule_group_t group, static int schedule_group_leave(odp_schedule_group_t group, const odp_thrmask_t *mask) { + odp_thrmask_t new_mask; int ret; + odp_thrmask_xor(&new_mask, mask, &sched->mask_all); + odp_spinlock_lock(&sched->grp_lock); if (group < NUM_SCHED_GRPS && group >= SCHED_GROUP_NAMED && sched->sched_grp[group].allocated) { - odp_thrmask_t leavemask; + odp_thrmask_and(&new_mask, &sched->sched_grp[group].mask, + &new_mask); + grp_update_mask(group, &new_mask); - odp_thrmask_xor(&leavemask, mask, &sched->mask_all); - odp_thrmask_and(&sched->sched_grp[group].mask, - &sched->sched_grp[group].mask, - &leavemask); ret = 0; } else { ret = -1; @@ -1159,12 +1280,19 @@ static int schedule_group_info(odp_schedule_group_t group, static int schedule_thr_add(odp_schedule_group_t group, int thr) { + odp_thrmask_t mask; + odp_thrmask_t new_mask; + if (group < 0 || group >= SCHED_GROUP_NAMED) return -1; + odp_thrmask_zero(&mask); + odp_thrmask_set(&mask, thr); + odp_spinlock_lock(&sched->grp_lock); - odp_thrmask_set(&sched->sched_grp[group].mask, thr); + odp_thrmask_or(&new_mask, &sched->sched_grp[group].mask, &mask); + grp_update_mask(group, &new_mask); odp_spinlock_unlock(&sched->grp_lock); @@ -1173,12 +1301,20 @@ static int schedule_thr_add(odp_schedule_group_t group, int thr) static int schedule_thr_rem(odp_schedule_group_t group, int thr) { + odp_thrmask_t mask; + odp_thrmask_t new_mask; + if (group < 0 || group >= SCHED_GROUP_NAMED) return -1; + odp_thrmask_zero(&mask); + odp_thrmask_set(&mask, thr); + odp_thrmask_xor(&new_mask, &mask, &sched->mask_all); + odp_spinlock_lock(&sched->grp_lock); - odp_thrmask_clr(&sched->sched_grp[group].mask, thr); + odp_thrmask_and(&new_mask, &sched->sched_grp[group].mask, &new_mask); + grp_update_mask(group, &new_mask); odp_spinlock_unlock(&sched->grp_lock); @@ -1192,9 +1328,10 @@ static void schedule_prefetch(int num ODP_UNUSED) static int schedule_sched_queue(uint32_t queue_index) { + int grp = sched->queue[queue_index].grp; int prio = sched->queue[queue_index].prio; int queue_per_prio = sched->queue[queue_index].queue_per_prio; - ring_t *ring = &sched->prio_q[prio][queue_per_prio].ring; + ring_t *ring = &sched->prio_q[grp][prio][queue_per_prio].ring; ring_enq(ring, PRIO_QUEUE_MASK, queue_index); return 0; diff --git a/platform/linux-generic/odp_schedule_iquery.c b/platform/linux-generic/odp_schedule_iquery.c index b69245788..75470aff8 100644 --- a/platform/linux-generic/odp_schedule_iquery.c +++ b/platform/linux-generic/odp_schedule_iquery.c @@ -21,6 +21,7 @@ #include <odp/api/hints.h> #include <odp/api/cpu.h> #include <odp/api/thrmask.h> +#include <odp/api/packet_io.h> #include <odp_config_internal.h> /* Number of priority levels */ @@ -1176,7 +1177,9 @@ static int schedule_ord_enq_multi(uint32_t queue_index, void *buf_hdr[], return 0; } - if (odp_unlikely(stash_num >= MAX_ORDERED_STASH)) { + /* Pktout may drop packets, so the operation cannot be stashed. */ + if (dst_queue->s.pktout.pktio != ODP_PKTIO_INVALID || + odp_unlikely(stash_num >= MAX_ORDERED_STASH)) { /* If the local stash is full, wait until it is our turn and * then release the stash and do enqueue directly. */ wait_for_order(src_queue); @@ -1457,7 +1460,7 @@ static inline int consume_queue(int prio, unsigned int queue_index) /* Low priorities have smaller batch size to limit * head of line blocking latency. */ - if (odp_unlikely(prio > ODP_SCHED_PRIO_DEFAULT)) + if (odp_unlikely(MAX_DEQ > 1 && prio > ODP_SCHED_PRIO_DEFAULT)) max = MAX_DEQ / 2; /* For ordered queues we want consecutive events to diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c index 18c61dbe7..40ffca078 100644 --- a/platform/linux-generic/odp_system_info.c +++ b/platform/linux-generic/odp_system_info.c @@ -14,6 +14,7 @@ #include <odp_posix_extensions.h> #include <odp/api/system_info.h> +#include <odp/api/version.h> #include <odp_internal.h> #include <odp_debug_internal.h> #include <odp/api/align.h> @@ -405,3 +406,32 @@ int odp_cpu_count(void) { return odp_global_data.system_info.cpu_count; } + +void odp_sys_info_print(void) +{ + int len; + int max_len = 512; + char str[max_len]; + + len = snprintf(str, max_len, "\n" + "ODP system info\n" + "---------------\n" + "ODP API version: %s\n" + "ODP impl name: %s\n" + "CPU model: %s\n" + "CPU freq (hz): %" PRIu64 "\n" + "Cache line size: %i\n" + "CPU count: %i\n" + "\n", + odp_version_api_str(), + odp_version_impl_name(), + odp_cpu_model_str(), + odp_cpu_hz_max(), + odp_sys_cache_line_size(), + odp_cpu_count()); + + str[len] = '\0'; + ODP_PRINT("%s", str); + + sys_info_print_arch(); +} diff --git a/platform/linux-generic/odp_time.c b/platform/linux-generic/odp_time.c index 81e05224c..2bbe56664 100644 --- a/platform/linux-generic/odp_time.c +++ b/platform/linux-generic/odp_time.c @@ -10,36 +10,43 @@ #include <odp/api/time.h> #include <odp/api/hints.h> #include <odp_debug_internal.h> +#include <odp_time_internal.h> +#include <string.h> +#include <inttypes.h> -static odp_time_t start_time; +typedef struct time_global_t { + struct timespec spec_start; + int use_hw; + uint64_t hw_start; + uint64_t hw_freq_hz; +} time_global_t; -static inline -uint64_t time_to_ns(odp_time_t time) -{ - uint64_t ns; - - ns = time.tv_sec * ODP_TIME_SEC_IN_NS; - ns += time.tv_nsec; +static time_global_t global; - return ns; -} +/* + * Posix timespec based functions + */ -static inline odp_time_t time_diff(odp_time_t t2, odp_time_t t1) +static inline uint64_t time_spec_diff_nsec(struct timespec *t2, + struct timespec *t1) { - odp_time_t time; + struct timespec diff; + uint64_t nsec; - time.tv_sec = t2.tv_sec - t1.tv_sec; - time.tv_nsec = t2.tv_nsec - t1.tv_nsec; + diff.tv_sec = t2->tv_sec - t1->tv_sec; + diff.tv_nsec = t2->tv_nsec - t1->tv_nsec; - if (time.tv_nsec < 0) { - time.tv_nsec += ODP_TIME_SEC_IN_NS; - --time.tv_sec; + if (diff.tv_nsec < 0) { + diff.tv_nsec += ODP_TIME_SEC_IN_NS; + diff.tv_sec -= 1; } - return time; + nsec = (diff.tv_sec * ODP_TIME_SEC_IN_NS) + diff.tv_nsec; + + return nsec; } -static inline odp_time_t time_local(void) +static inline odp_time_t time_spec_cur(void) { int ret; odp_time_t time; @@ -49,82 +56,176 @@ static inline odp_time_t time_local(void) if (odp_unlikely(ret != 0)) ODP_ABORT("clock_gettime failed\n"); - time.tv_sec = sys_time.tv_sec; - time.tv_nsec = sys_time.tv_nsec; + time.nsec = time_spec_diff_nsec(&sys_time, &global.spec_start); - return time_diff(time, start_time); + return time; } -static inline int time_cmp(odp_time_t t2, odp_time_t t1) +static inline uint64_t time_spec_res(void) { - if (t2.tv_sec < t1.tv_sec) - return -1; + int ret; + struct timespec tres; - if (t2.tv_sec > t1.tv_sec) - return 1; + ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres); + if (odp_unlikely(ret != 0)) + ODP_ABORT("clock_getres failed\n"); - return t2.tv_nsec - t1.tv_nsec; + return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec; } -static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2) +static inline uint64_t time_spec_to_ns(odp_time_t time) +{ + return time.nsec; +} + +static inline odp_time_t time_spec_from_ns(uint64_t ns) { odp_time_t time; - time.tv_sec = t2.tv_sec + t1.tv_sec; - time.tv_nsec = t2.tv_nsec + t1.tv_nsec; + time.nsec = ns; + + return time; +} + +/* + * HW time counter based functions + */ - if (time.tv_nsec >= (long)ODP_TIME_SEC_IN_NS) { - time.tv_nsec -= ODP_TIME_SEC_IN_NS; - ++time.tv_sec; +static inline odp_time_t time_hw_cur(void) +{ + odp_time_t time; + + time.count = cpu_global_time() - global.hw_start; + + return time; +} + +static inline uint64_t time_hw_res(void) +{ + /* Promise a bit lower resolution than average cycle counter + * frequency */ + return global.hw_freq_hz / 10; +} + +static inline uint64_t time_hw_to_ns(odp_time_t time) +{ + uint64_t nsec; + uint64_t freq_hz = global.hw_freq_hz; + uint64_t count = time.count; + uint64_t sec = 0; + + if (count >= freq_hz) { + sec = count / freq_hz; + count = count - sec * freq_hz; } + nsec = (ODP_TIME_SEC_IN_NS * count) / freq_hz; + + return (sec * ODP_TIME_SEC_IN_NS) + nsec; +} + +static inline odp_time_t time_hw_from_ns(uint64_t ns) +{ + odp_time_t time; + uint64_t count; + uint64_t freq_hz = global.hw_freq_hz; + uint64_t sec = 0; + + if (ns >= ODP_TIME_SEC_IN_NS) { + sec = ns / ODP_TIME_SEC_IN_NS; + ns = ns - sec * ODP_TIME_SEC_IN_NS; + } + + count = sec * freq_hz; + count += (ns * freq_hz) / ODP_TIME_SEC_IN_NS; + + time.count = count; + return time; } -static inline odp_time_t time_local_from_ns(uint64_t ns) +/* + * Common functions + */ + +static inline odp_time_t time_cur(void) +{ + if (global.use_hw) + return time_hw_cur(); + + return time_spec_cur(); +} + +static inline uint64_t time_res(void) +{ + if (global.use_hw) + return time_hw_res(); + + return time_spec_res(); +} + +static inline int time_cmp(odp_time_t t2, odp_time_t t1) +{ + if (odp_likely(t2.u64 > t1.u64)) + return 1; + + if (t2.u64 < t1.u64) + return -1; + + return 0; +} + +static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2) { odp_time_t time; - time.tv_sec = ns / ODP_TIME_SEC_IN_NS; - time.tv_nsec = ns - time.tv_sec * ODP_TIME_SEC_IN_NS; + time.u64 = t1.u64 + t2.u64; return time; } -static inline void time_wait_until(odp_time_t time) +static inline uint64_t time_to_ns(odp_time_t time) { - odp_time_t cur; + if (global.use_hw) + return time_hw_to_ns(time); - do { - cur = time_local(); - } while (time_cmp(time, cur) > 0); + return time_spec_to_ns(time); } -static inline uint64_t time_local_res(void) +static inline odp_time_t time_from_ns(uint64_t ns) { - int ret; - struct timespec tres; + if (global.use_hw) + return time_hw_from_ns(ns); - ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres); - if (odp_unlikely(ret != 0)) - ODP_ABORT("clock_getres failed\n"); + return time_spec_from_ns(ns); +} - return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec; +static inline void time_wait_until(odp_time_t time) +{ + odp_time_t cur; + + do { + cur = time_cur(); + } while (time_cmp(time, cur) > 0); } odp_time_t odp_time_local(void) { - return time_local(); + return time_cur(); } odp_time_t odp_time_global(void) { - return time_local(); + return time_cur(); } odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1) { - return time_diff(t2, t1); + odp_time_t time; + + time.u64 = t2.u64 - t1.u64; + + return time; } uint64_t odp_time_to_ns(odp_time_t time) @@ -134,12 +235,12 @@ uint64_t odp_time_to_ns(odp_time_t time) odp_time_t odp_time_local_from_ns(uint64_t ns) { - return time_local_from_ns(ns); + return time_from_ns(ns); } odp_time_t odp_time_global_from_ns(uint64_t ns) { - return time_local_from_ns(ns); + return time_from_ns(ns); } int odp_time_cmp(odp_time_t t2, odp_time_t t1) @@ -154,18 +255,18 @@ odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2) uint64_t odp_time_local_res(void) { - return time_local_res(); + return time_res(); } uint64_t odp_time_global_res(void) { - return time_local_res(); + return time_res(); } void odp_time_wait_ns(uint64_t ns) { - odp_time_t cur = time_local(); - odp_time_t wait = time_local_from_ns(ns); + odp_time_t cur = time_cur(); + odp_time_t wait = time_from_ns(ns); odp_time_t end_time = time_sum(cur, wait); time_wait_until(end_time); @@ -176,34 +277,31 @@ void odp_time_wait_until(odp_time_t time) return time_wait_until(time); } -uint64_t odp_time_to_u64(odp_time_t time) +int odp_time_init_global(void) { - int ret; - struct timespec tres; - uint64_t resolution; + int ret = 0; - ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres); - if (odp_unlikely(ret != 0)) - ODP_ABORT("clock_getres failed\n"); + memset(&global, 0, sizeof(time_global_t)); - resolution = (uint64_t)tres.tv_nsec; + if (cpu_has_global_time()) { + global.use_hw = 1; + global.hw_freq_hz = cpu_global_time_freq(); - return time_to_ns(time) / resolution; -} + if (global.hw_freq_hz == 0) + return -1; -int odp_time_init_global(void) -{ - int ret; - struct timespec time; - - ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time); - if (ret) { - start_time = ODP_TIME_NULL; - } else { - start_time.tv_sec = time.tv_sec; - start_time.tv_nsec = time.tv_nsec; + printf("HW time counter freq: %" PRIu64 " hz\n\n", + global.hw_freq_hz); + + global.hw_start = cpu_global_time(); + return 0; } + global.spec_start.tv_sec = 0; + global.spec_start.tv_nsec = 0; + + ret = clock_gettime(CLOCK_MONOTONIC_RAW, &global.spec_start); + return ret; } diff --git a/platform/linux-generic/odp_traffic_mngr.c b/platform/linux-generic/odp_traffic_mngr.c index 4e9358b96..a93b3ba90 100644 --- a/platform/linux-generic/odp_traffic_mngr.c +++ b/platform/linux-generic/odp_traffic_mngr.c @@ -3238,7 +3238,7 @@ static void tm_sched_params_cvt_to(odp_tm_sched_params_t *odp_sched_params, if (weight == 0) inv_weight = 0; else - inv_weight = 0x10000 / weight; + inv_weight = 0xFFFF / weight; tm_sched_params->sched_modes[priority] = sched_mode; tm_sched_params->inverted_weights[priority] = inv_weight; @@ -3254,7 +3254,7 @@ static void tm_sched_params_cvt_from(tm_sched_params_t *tm_sched_params, for (priority = 0; priority < ODP_TM_MAX_PRIORITIES; priority++) { sched_mode = tm_sched_params->sched_modes[priority]; inv_weight = tm_sched_params->inverted_weights[priority]; - weight = 0x10000 / inv_weight; + weight = 0xFFFF / inv_weight; odp_sched_params->sched_modes[priority] = sched_mode; odp_sched_params->sched_weights[priority] = weight; diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index 1922109a7..c52cd09d1 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -34,49 +34,6 @@ static int disable_pktio; /** !0 this pktio disabled, 0 enabled */ /* Has dpdk_pktio_init() been called */ static odp_bool_t dpdk_initialized; -#define PMD_EXT(drv) \ -extern void devinitfn_##drv(void) - -PMD_EXT(aesni_gcm_pmd_drv); -PMD_EXT(cryptodev_aesni_mb_pmd_drv); -PMD_EXT(cryptodev_kasumi_pmd_drv); -PMD_EXT(cryptodev_null_pmd_drv); -PMD_EXT(cryptodev_snow3g_pmd_drv); -PMD_EXT(pmd_qat_drv); -PMD_EXT(pmd_af_packet_drv); -PMD_EXT(rte_bnx2x_driver); -PMD_EXT(rte_bnx2xvf_driver); -PMD_EXT(bnxt_pmd_drv); -PMD_EXT(bond_drv); -PMD_EXT(rte_cxgbe_driver); -PMD_EXT(em_pmd_drv); -PMD_EXT(pmd_igb_drv); -PMD_EXT(pmd_igbvf_drv); -PMD_EXT(ena_pmd_drv); -PMD_EXT(rte_enic_driver); -PMD_EXT(rte_fm10k_driver); -PMD_EXT(rte_i40e_driver); -PMD_EXT(rte_i40evf_driver); -PMD_EXT(rte_ixgbe_driver); -PMD_EXT(rte_ixgbevf_driver); -PMD_EXT(rte_mlx4_driver); -PMD_EXT(rte_mlx5_driver); -PMD_EXT(pmd_mpipe_xgbe_drv); -PMD_EXT(pmd_mpipe_gbe_drv); -PMD_EXT(rte_nfp_net_driver); -PMD_EXT(pmd_null_drv); -PMD_EXT(pmd_pcap_drv); -PMD_EXT(rte_qede_driver); -PMD_EXT(rte_qedevf_driver); -PMD_EXT(pmd_ring_drv); -PMD_EXT(pmd_szedata2_drv); -PMD_EXT(rte_nicvf_driver); -PMD_EXT(pmd_vhost_drv); -PMD_EXT(rte_virtio_driver); -PMD_EXT(virtio_user_driver); -PMD_EXT(rte_vmxnet3_driver); -PMD_EXT(pmd_xenvirt_drv); - #define MEMPOOL_OPS(hdl) \ extern void mp_hdlr_init_##hdl(void) @@ -89,116 +46,11 @@ MEMPOOL_OPS(ops_stack); /* * This function is not called from anywhere, it's only purpose is to make sure * that if ODP and DPDK are statically linked to an application, the GCC - * constructors of the PMDs are linked as well. Otherwise the linker would omit - * them. It's not an issue with dynamic linking. */ + * constructors of mempool handlers are linked as well. Otherwise the linker + * would omit them. It's not an issue with dynamic linking. */ void refer_constructors(void); void refer_constructors(void) { -#ifdef RTE_LIBRTE_PMD_AESNI_GCM - devinitfn_aesni_gcm_pmd_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_AESNI_MB - devinitfn_cryptodev_aesni_mb_pmd_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_KASUMI - devinitfn_cryptodev_kasumi_pmd_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_NULL_CRYPTO - devinitfn_cryptodev_null_pmd_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_SNOW3G - devinitfn_cryptodev_snow3g_pmd_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_QAT - devinitfn_pmd_qat_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_AF_PACKET - devinitfn_pmd_af_packet_drv(); -#endif -#ifdef RTE_LIBRTE_BNX2X_PMD - devinitfn_rte_bnx2x_driver(); - devinitfn_rte_bnx2xvf_driver(); -#endif -#ifdef RTE_LIBRTE_BNXT_PMD - devinitfn_bnxt_pmd_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_BOND - devinitfn_bond_drv(); -#endif -#ifdef RTE_LIBRTE_CXGBE_PMD - devinitfn_rte_cxgbe_driver(); -#endif -#ifdef RTE_LIBRTE_EM_PMD - devinitfn_em_pmd_drv(); -#endif -#ifdef RTE_LIBRTE_IGB_PMD - devinitfn_pmd_igb_drv(); - devinitfn_pmd_igbvf_drv(); -#endif -#ifdef RTE_LIBRTE_ENA_PMD - devinitfn_ena_pmd_drv(); -#endif -#ifdef RTE_LIBRTE_ENIC_PMD - devinitfn_rte_enic_driver(); -#endif -#ifdef RTE_LIBRTE_FM10K_PMD - devinitfn_rte_fm10k_driver(); -#endif -#ifdef RTE_LIBRTE_I40E_PMD - devinitfn_rte_i40e_driver(); - devinitfn_rte_i40evf_driver(); -#endif -#ifdef RTE_LIBRTE_IXGBE_PMD - devinitfn_rte_ixgbe_driver(); - devinitfn_rte_ixgbevf_driver(); -#endif -#ifdef RTE_LIBRTE_MLX4_PMD - devinitfn_rte_mlx4_driver(); -#endif -#ifdef RTE_LIBRTE_MLX5_PMD - devinitfn_rte_mlx5_driver(); -#endif -#ifdef RTE_LIBRTE_MPIPE_PMD - devinitfn_pmd_mpipe_xgbe_drv() - devinitfn_pmd_mpipe_gbe_drv() -#endif -#ifdef RTE_LIBRTE_NFP_PMD - devinitfn_rte_nfp_net_driver(); -#endif -#ifdef RTE_LIBRTE_PMD_NULL - devinitfn_pmd_null_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_PCAP - devinitfn_pmd_pcap_drv(); -#endif -#ifdef RTE_LIBRTE_QEDE_PMD - devinitfn_rte_qede_driver(); - devinitfn_rte_qedevf_driver(); -#endif -#ifdef RTE_LIBRTE_PMD_RING - devinitfn_pmd_ring_drv(); -#endif -#ifdef RTE_LIBRTE_PMD_SZEDATA2 - devinitfn_pmd_szedata2_drv(); -#endif -#ifdef RTE_LIBRTE_THUNDERX_NICVF_PMD - devinitfn_rte_nicvf_driver(); -#endif -#ifdef RTE_LIBRTE_PMD_VHOST - devinitfn_pmd_vhost_drv(); -#endif -#ifdef RTE_LIBRTE_VIRTIO_PMD - devinitfn_rte_virtio_driver(); -#endif -#ifdef RTE_VIRTIO_USER - devinitfn_rte_virtio_driver(); -#endif -#ifdef RTE_LIBRTE_VMXNET3_PMD - devinitfn_rte_vmxnet3_driver(); -#endif -#ifdef RTE_LIBRTE_PMD_XENVIRT - devinitfn_pmd_xenvirt_drv(); -#endif mp_hdlr_init_ops_mp_mc(); mp_hdlr_init_ops_sp_sc(); mp_hdlr_init_ops_mp_sc(); @@ -801,7 +653,8 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); else - packet_parse_l2(&pkt_hdr->p, pkt_len); + packet_parse_layer(pkt_hdr, + pktio_entry->s.config.parser.layer); if (mbuf->ol_flags & PKT_RX_RSS_HASH) odp_packet_flow_hash_set(pkt, mbuf->hash.rss); diff --git a/platform/linux-generic/pktio/ethtool.c b/platform/linux-generic/pktio/ethtool.c index 1b0f25b2c..d8f9e12cb 100644 --- a/platform/linux-generic/pktio/ethtool.c +++ b/platform/linux-generic/pktio/ethtool.c @@ -158,6 +158,7 @@ int ethtool_stats_get_fd(int fd, const char *name, odp_pktio_stats_t *stats) { struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name); return ethtool_stats(fd, &ifr, stats); diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c index 70962839f..e9ad22ba2 100644 --- a/platform/linux-generic/pktio/loop.c +++ b/platform/linux-generic/pktio/loop.c @@ -132,7 +132,8 @@ static int loopback_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); else - packet_parse_l2(&pkt_hdr->p, pkt_len); + packet_parse_layer(pkt_hdr, + pktio_entry->s.config.parser.layer); packet_set_ts(pkt_hdr, ts); @@ -176,7 +177,7 @@ static int loopback_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, pktio_entry->s.stats.out_octets += bytes; } else { ODP_DBG("queue enqueue failed %i\n", ret); - return -1; + ret = -1; } odp_ticketlock_unlock(&pktio_entry->s.txl); diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c index ae3db34d9..928bb00af 100644 --- a/platform/linux-generic/pktio/netmap.c +++ b/platform/linux-generic/pktio/netmap.c @@ -663,7 +663,8 @@ static inline int netmap_pkt_to_odp(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); else - packet_parse_l2(&pkt_hdr->p, len); + packet_parse_layer(pkt_hdr, + pktio_entry->s.config.parser.layer); packet_set_ts(pkt_hdr, ts); } diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c index e54a56f5f..a467b6402 100644 --- a/platform/linux-generic/pktio/pcap.c +++ b/platform/linux-generic/pktio/pcap.c @@ -252,7 +252,8 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, int index ODP_UNUSED, break; } - packet_parse_l2(&pkt_hdr->p, pkt_len); + packet_parse_layer(pkt_hdr, + pktio_entry->s.config.parser.layer); pktio_entry->s.stats.in_octets += pkt_hdr->frame_len; packet_set_ts(pkt_hdr, ts); diff --git a/platform/linux-generic/pktio/ring.c b/platform/linux-generic/pktio/ring.c index aeda04b26..e3c73d1cb 100644 --- a/platform/linux-generic/pktio/ring.c +++ b/platform/linux-generic/pktio/ring.c @@ -263,8 +263,8 @@ int ___ring_mp_do_enqueue(_ring_t *r, void * const *obj_table, /* Reset n to the initial burst count */ n = max; - prod_head = r->prod.head; - cons_tail = r->cons.tail; + prod_head = __atomic_load_n(&r->prod.head, __ATOMIC_RELAXED); + cons_tail = __atomic_load_n(&r->cons.tail, __ATOMIC_ACQUIRE); /* The subtraction is done between two unsigned 32bits value * (the result is always modulo 32 bits even if we have * prod_head > cons_tail). So 'free_entries' is always between 0 @@ -306,12 +306,12 @@ int ___ring_mp_do_enqueue(_ring_t *r, void * const *obj_table, * If there are other enqueues in progress that preceded us, * we need to wait for them to complete */ - while (odp_unlikely(r->prod.tail != prod_head)) + while (odp_unlikely(__atomic_load_n(&r->prod.tail, __ATOMIC_RELAXED) != + prod_head)) odp_cpu_pause(); /* Release our entries and the memory they refer to */ - __atomic_thread_fence(__ATOMIC_RELEASE); - r->prod.tail = prod_next; + __atomic_store_n(&r->prod.tail, prod_next, __ATOMIC_RELEASE); return ret; } @@ -328,7 +328,7 @@ int ___ring_sp_do_enqueue(_ring_t *r, void * const *obj_table, int ret; prod_head = r->prod.head; - cons_tail = r->cons.tail; + cons_tail = __atomic_load_n(&r->cons.tail, __ATOMIC_ACQUIRE); /* The subtraction is done between two unsigned 32bits value * (the result is always modulo 32 bits even if we have * prod_head > cons_tail). So 'free_entries' is always between 0 @@ -361,8 +361,7 @@ int ___ring_sp_do_enqueue(_ring_t *r, void * const *obj_table, } /* Release our entries and the memory they refer to */ - __atomic_thread_fence(__ATOMIC_RELEASE); - r->prod.tail = prod_next; + __atomic_store_n(&r->prod.tail, prod_next, __ATOMIC_RELEASE); return ret; } @@ -385,8 +384,8 @@ int ___ring_mc_do_dequeue(_ring_t *r, void **obj_table, /* Restore n as it may change every loop */ n = max; - cons_head = r->cons.head; - prod_tail = r->prod.tail; + cons_head = __atomic_load_n(&r->cons.head, __ATOMIC_RELAXED); + prod_tail = __atomic_load_n(&r->prod.tail, __ATOMIC_ACQUIRE); /* The subtraction is done between two unsigned 32bits value * (the result is always modulo 32 bits even if we have * cons_head > prod_tail). So 'entries' is always between 0 @@ -419,12 +418,12 @@ int ___ring_mc_do_dequeue(_ring_t *r, void **obj_table, * If there are other dequeues in progress that preceded us, * we need to wait for them to complete */ - while (odp_unlikely(r->cons.tail != cons_head)) + while (odp_unlikely(__atomic_load_n(&r->cons.tail, __ATOMIC_RELAXED) != + cons_head)) odp_cpu_pause(); /* Release our entries and the memory they refer to */ - __atomic_thread_fence(__ATOMIC_RELEASE); - r->cons.tail = cons_next; + __atomic_store_n(&r->cons.tail, cons_next, __ATOMIC_RELEASE); return behavior == _RING_QUEUE_FIXED ? 0 : n; } @@ -441,7 +440,7 @@ int ___ring_sc_do_dequeue(_ring_t *r, void **obj_table, uint32_t mask = r->prod.mask; cons_head = r->cons.head; - prod_tail = r->prod.tail; + prod_tail = __atomic_load_n(&r->prod.tail, __ATOMIC_ACQUIRE); /* The subtraction is done between two unsigned 32bits value * (the result is always modulo 32 bits even if we have * cons_head > prod_tail). So 'entries' is always between 0 @@ -461,11 +460,10 @@ int ___ring_sc_do_dequeue(_ring_t *r, void **obj_table, r->cons.head = cons_next; /* Acquire the pointers and the memory they refer to */ - __atomic_thread_fence(__ATOMIC_ACQUIRE); /* copy in table */ DEQUEUE_PTRS(); - r->cons.tail = cons_next; + __atomic_store_n(&r->cons.tail, cons_next, __ATOMIC_RELEASE); return behavior == _RING_QUEUE_FIXED ? 0 : n; } diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c index 7d2396866..a383adc6a 100644 --- a/platform/linux-generic/pktio/socket.c +++ b/platform/linux-generic/pktio/socket.c @@ -234,6 +234,7 @@ static inline int get_rss_hash_options(int fd, const char *name, struct ifreq ifr; struct ethtool_rxnfc rsscmd; + memset(&ifr, 0, sizeof(ifr)); memset(&rsscmd, 0, sizeof(rsscmd)); *options = 0; @@ -461,8 +462,6 @@ static int sock_close(pktio_entry_t *pktio_entry) return -1; } - odp_shm_free(pkt_sock->shm); - return 0; } @@ -474,13 +473,11 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev, { int sockfd; int err; - int i; unsigned int if_idx; struct ifreq ethreq; struct sockaddr_ll sa_ll; char shm_name[ODP_SHM_NAME_LEN]; pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock; - uint8_t *addr; odp_pktio_stats_t cur_stats; /* Init pktio entry */ @@ -494,18 +491,6 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev, snprintf(shm_name, ODP_SHM_NAME_LEN, "%s-%s", "pktio", netdev); shm_name[ODP_SHM_NAME_LEN - 1] = '\0'; - pkt_sock->shm = odp_shm_reserve(shm_name, PACKET_JUMBO_LEN, - PACKET_JUMBO_LEN * - ODP_PACKET_SOCKET_MAX_BURST_RX, 0); - if (pkt_sock->shm == ODP_SHM_INVALID) - return -1; - - addr = odp_shm_addr(pkt_sock->shm); - for (i = 0; i < ODP_PACKET_SOCKET_MAX_BURST_RX; i++) { - pkt_sock->cache_ptr[i] = addr; - addr += PACKET_JUMBO_LEN; - } - sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sockfd == -1) { __odp_errno = errno; @@ -617,19 +602,17 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, odp_packet_t pkt_table[], int len) { pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock; + odp_pool_t pool = pkt_sock->pool; odp_time_t ts_val; odp_time_t *ts = NULL; const int sockfd = pkt_sock->sockfd; - int msgvec_len; - struct mmsghdr msgvec[ODP_PACKET_SOCKET_MAX_BURST_RX]; + struct mmsghdr msgvec[len]; + struct iovec iovecs[len][MAX_SEGS]; int nb_rx = 0; + int nb_pkts; int recv_msgs; - uint8_t **recv_cache; int i; - if (odp_unlikely(len > ODP_PACKET_SOCKET_MAX_BURST_RX)) - return -1; - odp_ticketlock_lock(&pktio_entry->s.rxl); if (pktio_entry->s.config.pktin.bit.ts_all || @@ -637,131 +620,72 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED, ts = &ts_val; memset(msgvec, 0, sizeof(msgvec)); - recv_cache = pkt_sock->cache_ptr; - if (pktio_cls_enabled(pktio_entry)) { - struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_RX]; + nb_pkts = packet_alloc_multi(pool, pkt_sock->mtu, pkt_table, len); + for (i = 0; i < nb_pkts; i++) { + msgvec[i].msg_hdr.msg_iovlen = + _rx_pkt_to_iovec(pkt_table[i], iovecs[i]); + msgvec[i].msg_hdr.msg_iov = iovecs[i]; + } + + recv_msgs = recvmmsg(sockfd, msgvec, nb_pkts, MSG_DONTWAIT, NULL); - for (i = 0; i < (int)len; i++) { - msgvec[i].msg_hdr.msg_iovlen = 1; - iovecs[i].iov_base = recv_cache[i]; - iovecs[i].iov_len = PACKET_JUMBO_LEN; - msgvec[i].msg_hdr.msg_iov = &iovecs[i]; - } - msgvec_len = i; - - recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len, - MSG_DONTWAIT, NULL); - - if (ts != NULL) - ts_val = odp_time_global(); - - for (i = 0; i < recv_msgs; i++) { - odp_packet_hdr_t *pkt_hdr; - odp_packet_t pkt; - odp_pool_t pool = pkt_sock->pool; - odp_packet_hdr_t parsed_hdr; - void *base = msgvec[i].msg_hdr.msg_iov->iov_base; - struct ethhdr *eth_hdr = base; - uint16_t pkt_len = msgvec[i].msg_len; - int num; - - /* Don't receive packets sent by ourselves */ - if (odp_unlikely(ethaddrs_equal(pkt_sock->if_mac, - eth_hdr->h_source))) - continue; + if (ts != NULL) + ts_val = odp_time_global(); - if (cls_classify_packet(pktio_entry, base, pkt_len, - pkt_len, &pool, &parsed_hdr)) - continue; + for (i = 0; i < recv_msgs; i++) { + void *base = msgvec[i].msg_hdr.msg_iov->iov_base; + struct ethhdr *eth_hdr = base; + odp_packet_t pkt = pkt_table[i]; + odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + uint16_t pkt_len = msgvec[i].msg_len; + int ret; - num = packet_alloc_multi(pool, pkt_len, &pkt, 1); - if (num != 1) - continue; + if (pktio_cls_enabled(pktio_entry)) { + uint16_t seg_len = pkt_len; - pkt_hdr = odp_packet_hdr(pkt); + if (msgvec[i].msg_hdr.msg_iov->iov_len < pkt_len) + seg_len = msgvec[i].msg_hdr.msg_iov->iov_len; - if (odp_packet_copy_from_mem(pkt, 0, pkt_len, - base) != 0) { + if (cls_classify_packet(pktio_entry, base, pkt_len, + seg_len, &pool, pkt_hdr)) { + ODP_ERR("cls_classify_packet failed"); odp_packet_free(pkt); continue; } - pkt_hdr->input = pktio_entry->s.handle; - copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); - packet_set_ts(pkt_hdr, ts); - - pkt_table[nb_rx++] = pkt; } - } else { - struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_RX] - [MAX_SEGS]; - - for (i = 0; i < (int)len; i++) { - int num; - num = packet_alloc_multi(pkt_sock->pool, pkt_sock->mtu, - &pkt_table[i], 1); - - if (odp_unlikely(num != 1)) { - pkt_table[i] = ODP_PACKET_INVALID; - break; - } - - msgvec[i].msg_hdr.msg_iovlen = - _rx_pkt_to_iovec(pkt_table[i], iovecs[i]); - - msgvec[i].msg_hdr.msg_iov = iovecs[i]; + /* Don't receive packets sent by ourselves */ + if (odp_unlikely(ethaddrs_equal(pkt_sock->if_mac, + eth_hdr->h_source))) { + odp_packet_free(pkt); + continue; } - /* number of successfully allocated pkt buffers */ - msgvec_len = i; - - recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len, - MSG_DONTWAIT, NULL); - - if (ts != NULL) - ts_val = odp_time_global(); - - for (i = 0; i < recv_msgs; i++) { - void *base = msgvec[i].msg_hdr.msg_iov->iov_base; - struct ethhdr *eth_hdr = base; - odp_packet_hdr_t *pkt_hdr; - odp_packet_t pkt; - int ret; - - pkt = pkt_table[i]; - - /* Don't receive packets sent by ourselves */ - if (odp_unlikely(ethaddrs_equal(pkt_sock->if_mac, - eth_hdr->h_source))) { - odp_packet_free(pkt); - continue; - } + ret = odp_packet_trunc_tail(&pkt, odp_packet_len(pkt) - pkt_len, + NULL, NULL); + if (ret < 0) { + ODP_ERR("trunk_tail failed"); + odp_packet_free(pkt); + continue; + } - /* Parse and set packet header data */ - ret = odp_packet_trunc_tail(&pkt, odp_packet_len(pkt) - - msgvec[i].msg_len, - NULL, NULL); - if (ret < 0) { - ODP_ERR("trunk_tail failed"); - odp_packet_free(pkt); - continue; - } + pkt_hdr->input = pktio_entry->s.handle; - pkt_hdr = odp_packet_hdr(pkt); - packet_parse_l2(&pkt_hdr->p, pkt_hdr->frame_len); - packet_set_ts(pkt_hdr, ts); - pkt_hdr->input = pktio_entry->s.handle; + if (!pktio_cls_enabled(pktio_entry)) + packet_parse_layer(pkt_hdr, + pktio_entry->s.config.parser.layer); - pkt_table[nb_rx] = pkt; - nb_rx++; - } + pkt_hdr->input = pktio_entry->s.handle; + packet_set_ts(pkt_hdr, ts); - /* Free unused pkt buffers */ - for (; i < msgvec_len; i++) - odp_packet_free(pkt_table[i]); + pkt_table[nb_rx++] = pkt; } + /* Free unused pkt buffers */ + for (; i < nb_pkts; i++) + odp_packet_free(pkt_table[i]); + odp_ticketlock_unlock(&pktio_entry->s.rxl); return nb_rx; @@ -793,15 +717,12 @@ static int sock_mmsg_send(pktio_entry_t *pktio_entry, int index ODP_UNUSED, const odp_packet_t pkt_table[], int len) { pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock; - struct mmsghdr msgvec[ODP_PACKET_SOCKET_MAX_BURST_TX]; - struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_TX][MAX_SEGS]; + struct mmsghdr msgvec[len]; + struct iovec iovecs[len][MAX_SEGS]; int ret; int sockfd; int n, i; - if (odp_unlikely(len > ODP_PACKET_SOCKET_MAX_BURST_TX)) - return -1; - odp_ticketlock_lock(&pktio_entry->s.txl); sockfd = pkt_sock->sockfd; diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c index 666aae6af..2dba7b08f 100644 --- a/platform/linux-generic/pktio/socket_mmap.c +++ b/platform/linux-generic/pktio/socket_mmap.c @@ -231,7 +231,8 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t *pktio_entry, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, hdr); else - packet_parse_l2(&hdr->p, pkt_len); + packet_parse_layer(hdr, + pktio_entry->s.config.parser.layer); packet_set_ts(hdr, ts); @@ -454,11 +455,11 @@ static int mmap_sock(pkt_sock_mmap_t *pkt_sock) return 0; } -static void mmap_unmap_sock(pkt_sock_mmap_t *pkt_sock) +static int mmap_unmap_sock(pkt_sock_mmap_t *pkt_sock) { - munmap(pkt_sock->mmap_base, pkt_sock->mmap_len); free(pkt_sock->rx_ring.rd); free(pkt_sock->tx_ring.rd); + return munmap(pkt_sock->mmap_base, pkt_sock->mmap_len); } static int mmap_bind_sock(pkt_sock_mmap_t *pkt_sock, const char *netdev) @@ -486,8 +487,14 @@ static int mmap_bind_sock(pkt_sock_mmap_t *pkt_sock, const char *netdev) static int sock_mmap_close(pktio_entry_t *entry) { pkt_sock_mmap_t *const pkt_sock = &entry->s.pkt_sock_mmap; + int ret; + + ret = mmap_unmap_sock(pkt_sock); + if (ret != 0) { + ODP_ERR("mmap_unmap_sock() %s\n", strerror(errno)); + return -1; + } - mmap_unmap_sock(pkt_sock); if (pkt_sock->sockfd != -1 && close(pkt_sock->sockfd) != 0) { __odp_errno = errno; ODP_ERR("close(sockfd): %s\n", strerror(errno)); diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c index ac2045606..650c12a77 100644 --- a/platform/linux-generic/pktio/tap.c +++ b/platform/linux-generic/pktio/tap.c @@ -213,7 +213,8 @@ static odp_packet_t pack_odp_pkt(pktio_entry_t *pktio_entry, const void *data, if (pktio_cls_enabled(pktio_entry)) copy_packet_cls_metadata(&parsed_hdr, pkt_hdr); else - packet_parse_l2(&pkt_hdr->p, len); + packet_parse_layer(pkt_hdr, + pktio_entry->s.config.parser.layer); packet_set_ts(pkt_hdr, ts); pkt_hdr->input = pktio_entry->s.handle; |