diff options
Diffstat (limited to 'platform/linux-dpdk')
-rw-r--r-- | platform/linux-dpdk/Makefile.am | 32 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp_buffer_internal.h | 1 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp_config_internal.h | 13 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp_eventdev_internal.h | 2 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp_queue_basic_internal.h | 3 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_crypto.c | 91 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_init.c | 1 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_packet.c | 106 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_pool.c | 2 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_queue_basic.c | 34 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_queue_eventdev.c | 2 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_schedule_if.c | 8 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_shared_memory.c | 21 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_system_info.c | 2 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_thread.c | 2 |
15 files changed, 266 insertions, 54 deletions
diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am index 61b61f6d6..279aed0c1 100644 --- a/platform/linux-dpdk/Makefile.am +++ b/platform/linux-dpdk/Makefile.am @@ -242,12 +242,13 @@ __LIB__libodp_dpdk_la_SOURCES += arch/default/odp_atomic.c \ arch/default/odp_cpu_cycles.c \ arch/default/odp_hash_crc32.c \ arch/arm/odp_sysinfo_parse.c -odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_inlines.h \ - arch/default/odp/api/abi/cpu_time.h \ +odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_time.h \ arch/default/odp/api/abi/hash_crc32.h if !ODP_ABI_COMPAT odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/atomic_generic.h \ arch/default/odp/api/abi/atomic_inlines.h \ + arch/default/odp/api/abi/cpu_generic.h \ + arch/arm/odp/api/abi/cpu_inlines.h \ arch/arm/odp/api/abi/cpu.h endif noinst_HEADERS += arch/arm/odp_atomic.h \ @@ -264,14 +265,15 @@ __LIB__libodp_dpdk_la_SOURCES += arch/aarch64/odp_atomic.c \ arch/aarch64/odp_global_time.c \ arch/default/odp_hash_crc32.c \ arch/aarch64/odp_sysinfo_parse.c -odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_inlines.h \ - arch/aarch64/odp/api/abi/cpu_time.h \ +odpapiabiarchinclude_HEADERS += arch/aarch64/odp/api/abi/cpu_time.h \ arch/aarch64/odp/api/abi/hash_crc32.h if !ODP_ABI_COMPAT odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/atomic_generic.h \ arch/aarch64/odp/api/abi/atomic_inlines.h \ arch/aarch64/odp/api/abi/atomic.h \ - arch/aarch64/odp/api/abi/cpu.h + arch/default/odp/api/abi/cpu_generic.h \ + arch/aarch64/odp/api/abi/cpu_inlines.h \ + arch/aarch64/odp/api/abi/cpu.h endif noinst_HEADERS += arch/aarch64/odp_atomic.h \ arch/aarch64/odp_cpu.h \ @@ -284,12 +286,13 @@ __LIB__libodp_dpdk_la_SOURCES += arch/default/odp_atomic.c \ arch/default/odp_global_time.c \ arch/default/odp_hash_crc32.c \ arch/default/odp_sysinfo_parse.c -odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_inlines.h \ - arch/default/odp/api/abi/cpu_time.h \ +odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_time.h \ arch/default/odp/api/abi/hash_crc32.h if !ODP_ABI_COMPAT odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/atomic_generic.h \ arch/default/odp/api/abi/atomic_inlines.h \ + arch/default/odp/api/abi/cpu_generic.h \ + arch/default/odp/api/abi/cpu_inlines.h \ arch/default/odp/api/abi/cpu.h endif noinst_HEADERS += arch/default/odp_atomic.h \ @@ -298,16 +301,16 @@ noinst_HEADERS += arch/default/odp_atomic.h \ endif if ARCH_IS_MIPS64 __LIB__libodp_dpdk_la_SOURCES += arch/default/odp_atomic.c \ - arch/mips64/odp_cpu_cycles.c \ arch/default/odp_global_time.c \ arch/default/odp_hash_crc32.c \ arch/mips64/odp_sysinfo_parse.c -odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_inlines.h \ - arch/default/odp/api/abi/cpu_time.h \ +odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_time.h \ arch/default/odp/api/abi/hash_crc32.h if !ODP_ABI_COMPAT odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/atomic_generic.h \ arch/default/odp/api/abi/atomic_inlines.h \ + arch/default/odp/api/abi/cpu_generic.h \ + arch/mips64/odp/api/abi/cpu_inlines.h \ arch/mips64/odp/api/abi/cpu.h endif noinst_HEADERS += arch/default/odp_atomic.h \ @@ -320,12 +323,13 @@ __LIB__libodp_dpdk_la_SOURCES += arch/default/odp_atomic.c \ arch/default/odp_global_time.c \ arch/default/odp_hash_crc32.c \ arch/powerpc/odp_sysinfo_parse.c -odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_inlines.h \ - arch/default/odp/api/abi/cpu_time.h \ +odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/cpu_time.h \ arch/default/odp/api/abi/hash_crc32.h if !ODP_ABI_COMPAT odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/atomic_generic.h \ arch/default/odp/api/abi/atomic_inlines.h \ + arch/default/odp/api/abi/cpu_generic.h \ + arch/default/odp/api/abi/cpu_inlines.h \ arch/powerpc/odp/api/abi/cpu.h endif noinst_HEADERS += arch/default/odp_atomic.h \ @@ -339,13 +343,13 @@ __LIB__libodp_dpdk_la_SOURCES += arch/default/odp_atomic.c \ arch/x86/odp_global_time.c \ arch/default/odp_hash_crc32.c \ arch/x86/odp_sysinfo_parse.c -odpapiabiarchinclude_HEADERS += arch/x86/odp/api/abi/cpu_inlines.h \ - arch/x86/odp/api/abi/cpu_rdtsc.h \ +odpapiabiarchinclude_HEADERS += arch/x86/odp/api/abi/cpu_rdtsc.h \ arch/x86/odp/api/abi/cpu_time.h \ arch/x86/odp/api/abi/hash_crc32.h if !ODP_ABI_COMPAT odpapiabiarchinclude_HEADERS += arch/default/odp/api/abi/atomic_generic.h \ arch/default/odp/api/abi/atomic_inlines.h \ + arch/x86/odp/api/abi/cpu_inlines.h \ arch/x86/odp/api/abi/cpu.h endif noinst_HEADERS += arch/x86/cpu_flags.h \ diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h b/platform/linux-dpdk/include/odp_buffer_internal.h index 37e5d1b4f..e47030ea7 100644 --- a/platform/linux-dpdk/include/odp_buffer_internal.h +++ b/platform/linux-dpdk/include/odp_buffer_internal.h @@ -29,7 +29,6 @@ extern "C" { #include <sys/types.h> #include <odp/api/event.h> #include <odp_forward_typedefs_internal.h> -#include <odp_schedule_if.h> #include <stddef.h> /* DPDK */ diff --git a/platform/linux-dpdk/include/odp_config_internal.h b/platform/linux-dpdk/include/odp_config_internal.h index 73d2304c9..6618d413d 100644 --- a/platform/linux-dpdk/include/odp_config_internal.h +++ b/platform/linux-dpdk/include/odp_config_internal.h @@ -124,11 +124,18 @@ extern "C" { CONFIG_PACKET_HEADROOM - \ CONFIG_PACKET_TAILROOM) -/* Maximum number of shared memory blocks. +/* + * Number of shared memory blocks reserved for implementation internal use. + */ +#define CONFIG_INTERNAL_SHM_BLOCKS 20 + +/* + * Maximum number of shared memory blocks. * - * This the number of separate SHM areas that can be reserved concurrently + * This is the number of separate SHM blocks that an application can reserve + * concurrently. */ -#define ODP_CONFIG_SHM_BLOCKS (ODP_CONFIG_POOLS + 48) +#define CONFIG_SHM_BLOCKS 64 /* * Maximum event burst size diff --git a/platform/linux-dpdk/include/odp_eventdev_internal.h b/platform/linux-dpdk/include/odp_eventdev_internal.h index 496a2238f..9e1083fd5 100644 --- a/platform/linux-dpdk/include/odp_eventdev_internal.h +++ b/platform/linux-dpdk/include/odp_eventdev_internal.h @@ -36,6 +36,8 @@ extern "C" { #include <stdint.h> +#define _ODP_SCHED_ID_EVENTDEV (_ODP_SCHED_ID_SCALABLE + 1) + #define RX_ADAPTER_INIT 0 #define RX_ADAPTER_STOPPED 1 #define RX_ADAPTER_RUNNING 2 diff --git a/platform/linux-dpdk/include/odp_queue_basic_internal.h b/platform/linux-dpdk/include/odp_queue_basic_internal.h index c3ddaf334..1e542d973 100644 --- a/platform/linux-dpdk/include/odp_queue_basic_internal.h +++ b/platform/linux-dpdk/include/odp_queue_basic_internal.h @@ -116,6 +116,9 @@ int _odp_sched_queue_deq(uint32_t queue_index, odp_event_t ev[], int num, int update_status); int _odp_sched_queue_empty(uint32_t queue_index); +/* Functions by schedulers */ +int _odp_sched_basic_get_spread(uint32_t queue_index); + #ifdef __cplusplus } #endif diff --git a/platform/linux-dpdk/odp_crypto.c b/platform/linux-dpdk/odp_crypto.c index 8ed561534..13e646230 100644 --- a/platform/linux-dpdk/odp_crypto.c +++ b/platform/linux-dpdk/odp_crypto.c @@ -64,8 +64,11 @@ typedef struct crypto_session_entry_s { struct rte_cryptodev_sym_session *rte_session; struct rte_crypto_sym_xform cipher_xform; struct rte_crypto_sym_xform auth_xform; + struct { + unsigned int cdev_qpairs_shared:1; + unsigned int chained_bufs_ok:1; + } flags; uint16_t cdev_nb_qpairs; - odp_bool_t cdev_qpairs_shared; uint8_t cdev_id; uint8_t cipher_iv_data[MAX_IV_LENGTH]; uint8_t auth_iv_data[MAX_IV_LENGTH]; @@ -312,7 +315,7 @@ int _odp_crypto_init_global(void) mem_size += (MAX_SESSIONS * sizeof(crypto_session_entry_t)); /* Allocate our globally shared memory */ - shm = odp_shm_reserve("_odp_crypto_glb", mem_size, + shm = odp_shm_reserve("_odp_crypto_global", mem_size, ODP_CACHE_LINE_SIZE, 0); if (shm != ODP_SHM_INVALID) { global = odp_shm_addr(shm); @@ -1260,6 +1263,34 @@ check_finish: return -1; } +static int chained_bufs_ok(const odp_crypto_session_param_t *param, + uint8_t cdev_id) +{ + struct rte_cryptodev_info dev_info; + int chained_bufs_ok; + + rte_cryptodev_info_get(cdev_id, &dev_info); + chained_bufs_ok = !!(dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL); + + /* + * Some crypto devices do not support chained buffers with all + * algorithms despite advertizing SG support in feature flags. + */ + + if (dev_info.driver_name && + !strcmp(dev_info.driver_name, "crypto_aesni_gcm") && + param->auth_alg == ODP_AUTH_ALG_AES_GMAC) + chained_bufs_ok = 0; + + if (dev_info.driver_name && + !strcmp(dev_info.driver_name, "crypto_openssl") && + (param->cipher_alg == ODP_CIPHER_ALG_AES_GCM || + param->auth_alg == ODP_AUTH_ALG_AES_GMAC)) + chained_bufs_ok = 0; + + return chained_bufs_ok; +} + #if RTE_VERSION < RTE_VERSION_NUM(19, 8, 0, 0) static int crypto_init_key(uint8_t **data, uint16_t *length, odp_crypto_key_t *key, const char *type) @@ -1482,6 +1513,7 @@ int odp_crypto_session_create(const odp_crypto_session_param_t *param, param->auth_alg == ODP_AUTH_ALG_NULL) { rte_session = NULL; cdev_id = ~0; + session->flags.chained_bufs_ok = 1; session->cdev_nb_qpairs = 0; goto out_null; } else if (param->cipher_alg == ODP_CIPHER_ALG_NULL) { @@ -1524,8 +1556,12 @@ int odp_crypto_session_create(const odp_crypto_session_param_t *param, goto err; } + session->flags.chained_bufs_ok = chained_bufs_ok(param, cdev_id); session->cdev_nb_qpairs = global->enabled_crypto_dev_qpairs[cdev_id]; - session->cdev_qpairs_shared = global->enabled_crypto_dev_qpairs_shared[cdev_id]; + if (global->enabled_crypto_dev_qpairs_shared[cdev_id]) + session->flags.cdev_qpairs_shared = 1; + else + session->flags.cdev_qpairs_shared = 0; out_null: session->rte_session = rte_session; session->cdev_id = cdev_id; @@ -1840,6 +1876,50 @@ static void crypto_fill_sym_param(crypto_session_entry_t *session, op->sym->auth.data.length = param->auth_range.length; } +/* + * Attempt to change a multi segment packet to a single segment packet by + * reducing the headroom. Shift packet data toward the start of the first + * segment and trim the tail, hopefully getting rid of the tail segment. + * + * This fails if the packet data does not fit in the first segment with + * the new headroom. A temporary copy to a bigger buffer would be needed + * in that case. + * + * Do nothing for single segment packets. + * + * We assume that odp_crypto_operation() makes no promise to not shift + * packet data within the packet. If that is not the case, the shifting + * done here needs to be undone after the crypto operation. + * + */ +static int linearize_pkt(const crypto_session_entry_t *session, odp_packet_t pkt) +{ + const uint32_t new_headroom = CONFIG_PACKET_HEADROOM; + uint32_t headroom; + uint32_t len; + uint32_t shift; + int rc; + + if (odp_likely(odp_packet_num_segs(pkt) == 1)) + return 0; + if (session->flags.chained_bufs_ok) + return 0; + + headroom = odp_packet_headroom(pkt); + if (odp_unlikely(new_headroom >= headroom)) + return -1; + + len = odp_packet_len(pkt); + shift = headroom - new_headroom; + odp_packet_push_head(pkt, shift); + odp_packet_move_data(pkt, 0, shift, len); + /* We rely on our trunc implementation to not change the handle */ + rc = odp_packet_trunc_tail(&pkt, shift, NULL, NULL); + ODP_ASSERT(rc == 0); + + return odp_packet_num_segs(pkt) != 1; +} + static int odp_crypto_int(odp_packet_t pkt_in, odp_packet_t *pkt_out, @@ -1896,6 +1976,9 @@ int odp_crypto_int(odp_packet_t pkt_in, pkt_in = ODP_PACKET_INVALID; } + if (linearize_pkt(session, out_pkt)) + goto err; + rte_session = session->rte_session; /* NULL rte_session means that it is a NULL-NULL operation. * Just return new packet. */ @@ -1914,7 +1997,7 @@ int odp_crypto_int(odp_packet_t pkt_in, int retry_count = 0; int queue_pair; int rc; - odp_bool_t queue_pairs_shared = session->cdev_qpairs_shared; + odp_bool_t queue_pairs_shared = session->flags.cdev_qpairs_shared; if (odp_unlikely(queue_pairs_shared)) queue_pair = odp_thread_id() % session->cdev_nb_qpairs; diff --git a/platform/linux-dpdk/odp_init.c b/platform/linux-dpdk/odp_init.c index 914a48fad..45f00f8ac 100644 --- a/platform/linux-dpdk/odp_init.c +++ b/platform/linux-dpdk/odp_init.c @@ -74,6 +74,7 @@ static void disable_features(odp_global_data_ro_t *global_ro, if (disable_ipsec && disable_crypto) global_ro->disable.crypto = 1; + global_ro->disable.stash = init_param->not_used.feat.stash; global_ro->disable.traffic_mngr = init_param->not_used.feat.tm; global_ro->disable.compress = init_param->not_used.feat.compress; } diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c index f5af3ce72..065a182a8 100644 --- a/platform/linux-dpdk/odp_packet.c +++ b/platform/linux-dpdk/odp_packet.c @@ -9,6 +9,7 @@ #include <odp/api/plat/packet_inlines.h> #include <odp_packet_internal.h> #include <odp_debug_internal.h> +#include <odp_macros_internal.h> #include <odp_chksum_internal.h> #include <odp/api/hints.h> #include <odp/api/byteorder.h> @@ -365,8 +366,8 @@ int odp_packet_extend_head(odp_packet_t *pkt, uint32_t len, void **data_ptr, } /* Expand the original head segment*/ newhead->pkt_len += rte_pktmbuf_headroom(mb); + mb->data_len += rte_pktmbuf_headroom(mb); mb->data_off = 0; - mb->data_len = mb->buf_len; _copy_head_metadata(newhead, mb); mb = newhead; *pkt = (odp_packet_t)newhead; @@ -522,11 +523,18 @@ int odp_packet_trunc_tail(odp_packet_t *pkt, uint32_t len, void **tail_ptr, uint32_t *tailroom) { struct rte_mbuf *mb = pkt_to_mbuf(*pkt); + struct rte_mbuf *last_mb = rte_pktmbuf_lastseg(mb); if (odp_unlikely(len >= odp_packet_len(*pkt))) return -1; - if (rte_pktmbuf_trim(mb, len)) { + /* + * Trim only if the last segment does not become zero length. + */ + if (odp_likely(len < last_mb->data_len)) { + if (odp_unlikely(rte_pktmbuf_trim(mb, len))) + return -1; + } else { struct rte_mbuf *reverse[mb->nb_segs]; struct rte_mbuf *t = mb; int i; @@ -1311,7 +1319,15 @@ static uint32_t packet_sum_crc32c(odp_packet_hdr_t *pkt_hdr, return sum; } -/** Parser helper function for Ethernet packets */ +/* + * In the worst case we look at the Ethernet header, 8 bytes of LLC/SNAP + * header and two VLAN tags in the same packet. + */ +#define PARSE_ETH_BYTES (sizeof(_odp_ethhdr_t) + 8 + 2 * sizeof(_odp_vlanhdr_t)) +/** Parser helper function for Ethernet packets + * + * Requires up to PARSE_ETH_BYTES bytes of contiguous packet data. + */ static inline uint16_t parse_eth(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset, uint32_t frame_len) { @@ -1328,7 +1344,7 @@ static inline uint16_t parse_eth(packet_parser_t *prs, const uint8_t **parseptr, eth = (const _odp_ethhdr_t *)*parseptr; /* Detect jumbo frames */ - if (odp_unlikely(frame_len > _ODP_ETH_LEN_MAX)) + if (odp_unlikely(frame_len - *offset > _ODP_ETH_LEN_MAX)) input_flags.jumbo = 1; /* Handle Ethernet broadcast/multicast addresses */ @@ -1386,14 +1402,27 @@ static inline uint16_t parse_eth(packet_parser_t *prs, const uint8_t **parseptr, *parseptr += sizeof(_odp_vlanhdr_t); } + /* + * The packet was too short for what we parsed. We just give up + * entirely without trying to parse what fits in the packet. + */ + if (odp_unlikely(*offset > frame_len)) { + input_flags.all = 0; + input_flags.l2 = 1; + ethtype = 0; + } + error: prs->input_flags.all |= input_flags.all; return ethtype; } +#define PARSE_IPV4_BYTES (0xfU * 4) /* max IPv4 header length with options */ /** * Parser helper function for IPv4 + * + * Requires up to PARSE_IPV4_BYTES bytes of contiguous packet data. */ static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset, uint32_t frame_len, @@ -1409,6 +1438,7 @@ static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN || ver != 4 || + sizeof(*ipv4) > frame_len - *offset || (l3_len > frame_len - *offset))) { prs->flags.ip_err = 1; return 0; @@ -1451,8 +1481,15 @@ static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, return ipv4->proto; } +/* + * Peeks 2 bytes beyond IPv6 base header without length check if there + * are extension headers. + */ +#define PARSE_IPV6_BYTES (sizeof(_odp_ipv6hdr_t) + 2) /** * Parser helper function for IPv6 + * + * Requires at least PARSE_IPV6_BYTES bytes of contiguous packet data. */ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset, uint32_t frame_len, @@ -1467,8 +1504,9 @@ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, _ODP_IPV6HDR_LEN; /* Basic sanity checks on IPv6 header */ - if ((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || - l3_len > frame_len - *offset) { + if (odp_unlikely((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || + sizeof(*ipv6) > frame_len - *offset || + l3_len > frame_len - *offset)) { prs->flags.ip_err = 1; return 0; } @@ -1520,8 +1558,11 @@ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, return ipv6->next_hdr; } +#define PARSE_TCP_BYTES (sizeof(_odp_tcphdr_t)) /** * Parser helper function for TCP + * + * Requires PARSE_TCP_BYTES bytes of contiguous packet data. */ static inline void parse_tcp(packet_parser_t *prs, const uint8_t **parseptr, uint16_t tcp_len, @@ -1547,8 +1588,15 @@ static inline void parse_tcp(packet_parser_t *prs, const uint8_t **parseptr, *parseptr += len; } +/* + * In the worst case we look at the UDP header and 4 bytes of the UDP + * payload (the non-ESP marker to distinguish IKE packets from ESP packets). + */ +#define PARSE_UDP_BYTES (sizeof(_odp_udphdr_t) + 4) /** * Parser helper function for UDP + * + * Requires PARSE_UDP_BYTES bytes of contiguous packet data. */ static inline void parse_udp(packet_parser_t *prs, const uint8_t **parseptr, odp_proto_chksums_t chksums, @@ -1593,8 +1641,11 @@ static inline void parse_udp(packet_parser_t *prs, const uint8_t **parseptr, *parseptr += sizeof(_odp_udphdr_t); } +#define PARSE_SCTP_BYTES (sizeof(_odp_sctphdr_t)) /** * Parser helper function for SCTP + * + * Requires PARSE_SCTP_BYTES bytes of contiguous packet data. */ static inline void parse_sctp(packet_parser_t *prs, const uint8_t **parseptr, uint16_t sctp_len, @@ -1621,6 +1672,10 @@ static inline void parse_sctp(packet_parser_t *prs, const uint8_t **parseptr, *parseptr += sizeof(_odp_sctphdr_t); } +#define MAX3(a, b, c) (MAX(MAX((a), (b)), (c))) +#define PARSE_L3_L4_BYTES (MAX(PARSE_IPV4_BYTES, PARSE_IPV6_BYTES) + \ + MAX3(PARSE_TCP_BYTES, PARSE_UDP_BYTES, PARSE_SCTP_BYTES)) +/* Requires up to PARSE_L3_L4_BYTES bytes of contiguous packet data. */ static inline int packet_parse_common_l3_l4(packet_parser_t *prs, const uint8_t *parseptr, uint32_t offset, @@ -1984,6 +2039,8 @@ static int packet_l4_chksum(odp_packet_hdr_t *pkt_hdr, if (chksums.chksum.sctp && pkt_hdr->p.input_flags.sctp && !pkt_hdr->p.input_flags.ipfrag) { + uint32_t seg_len = 0; + _odp_sctphdr_t hdr_copy; uint32_t sum = ~packet_sum_crc32c(pkt_hdr, pkt_hdr->p.l4_offset + _ODP_SCTPHDR_LEN, @@ -1993,8 +2050,14 @@ static int packet_l4_chksum(odp_packet_hdr_t *pkt_hdr, l4_part_sum); _odp_sctphdr_t *sctp = odp_packet_offset(packet_handle(pkt_hdr), pkt_hdr->p.l4_offset, - NULL, NULL); + &seg_len, NULL); + if (odp_unlikely(seg_len < sizeof(*sctp))) { + odp_packet_t pkt = packet_handle(pkt_hdr); + sctp = &hdr_copy; + odp_packet_copy_to_mem(pkt, pkt_hdr->p.l4_offset, + sizeof(*sctp), sctp); + } pkt_hdr->p.input_flags.l4_chksum_done = 1; if (sum != sctp->chksum) { pkt_hdr->p.flags.l4_chksum_err = 1; @@ -2051,12 +2114,14 @@ int odp_packet_parse(odp_packet_t pkt, uint32_t offset, odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); const uint8_t *data; uint32_t seg_len; - uint32_t len = odp_packet_len(pkt); + uint32_t packet_len = odp_packet_len(pkt); odp_proto_t proto = param->proto; odp_proto_layer_t layer = param->last_layer; int ret; uint16_t ethtype; uint64_t l4_part_sum = 0; + const uint32_t min_seglen = PARSE_ETH_BYTES + PARSE_L3_L4_BYTES; + uint8_t buf[min_seglen]; if (proto == ODP_PROTO_NONE || layer == ODP_PROTO_LAYER_NONE) return -1; @@ -2066,6 +2131,20 @@ int odp_packet_parse(odp_packet_t pkt, uint32_t offset, if (data == NULL) return -1; + /* + * We must not have a packet segment boundary within the parsed + * packet data range. Copy enough data to a temporary buffer for + * parsing if necessary. + */ + if (odp_unlikely(pkt_hdr->buf_hdr.mb.nb_segs > 1) && + odp_unlikely(seg_len < min_seglen)) { + seg_len = min_seglen; + if (seg_len > packet_len - offset) + seg_len = packet_len - offset; + odp_packet_copy_to_mem(pkt, offset, seg_len, buf); + data = buf; + } + /* Reset parser flags, keep other flags */ packet_parse_reset(pkt_hdr, 0); @@ -2073,7 +2152,7 @@ int odp_packet_parse(odp_packet_t pkt, uint32_t offset, /* Assume valid L2 header, no CRC/FCS check in SW */ pkt_hdr->p.l2_offset = offset; - ethtype = parse_eth(&pkt_hdr->p, &data, &offset, len); + ethtype = parse_eth(&pkt_hdr->p, &data, &offset, packet_len); } else if (proto == ODP_PROTO_IPV4) { ethtype = _ODP_ETHTYPE_IPV4; } else if (proto == ODP_PROTO_IPV6) { @@ -2083,7 +2162,7 @@ int odp_packet_parse(odp_packet_t pkt, uint32_t offset, } ret = packet_parse_common_l3_l4(&pkt_hdr->p, data, offset, - len, seg_len, + packet_len, seg_len, layer, ethtype, param->chksums, &l4_part_sum); @@ -2404,6 +2483,13 @@ odp_packet_reass_status_t odp_packet_reass_status(odp_packet_t pkt) return ODP_PACKET_REASS_NONE; } +int odp_packet_reass_info(odp_packet_t pkt, odp_packet_reass_info_t *info) +{ + (void)pkt; + (void)info; + return -1; +} + int odp_packet_reass_partial_state(odp_packet_t pkt, odp_packet_t frags[], odp_packet_reass_partial_state_t *res) { diff --git a/platform/linux-dpdk/odp_pool.c b/platform/linux-dpdk/odp_pool.c index 4b5eb3206..4417ca4ee 100644 --- a/platform/linux-dpdk/odp_pool.c +++ b/platform/linux-dpdk/odp_pool.c @@ -153,7 +153,7 @@ int _odp_pool_init_global(void) uint32_t i; odp_shm_t shm; - shm = odp_shm_reserve("_odp_pool_glb", sizeof(pool_global_t), + shm = odp_shm_reserve("_odp_pool_global", sizeof(pool_global_t), ODP_CACHE_LINE_SIZE, 0); _odp_pool_glb = odp_shm_addr(shm); diff --git a/platform/linux-dpdk/odp_queue_basic.c b/platform/linux-dpdk/odp_queue_basic.c index 7145fb2ce..33e0ba6bc 100644 --- a/platform/linux-dpdk/odp_queue_basic.c +++ b/platform/linux-dpdk/odp_queue_basic.c @@ -130,7 +130,7 @@ static int queue_init_global(void) _odp_queue_inline_offset.context = offsetof(queue_entry_t, s.param.context); - shm = odp_shm_reserve("_odp_queue_gbl", + shm = odp_shm_reserve("_odp_queue_basic_global", sizeof(queue_global_t), sizeof(queue_entry_t), 0); @@ -634,7 +634,8 @@ static void queue_print(odp_queue_t handle) odp_pktio_info_t pktio_info; queue_entry_t *queue; uint32_t queue_id; - int status; + int status, prio; + int max_prio = odp_schedule_max_prio(); queue_id = queue_to_index(handle); @@ -658,7 +659,7 @@ static void queue_print(odp_queue_t handle) ODP_PRINT("\nQueue info\n"); ODP_PRINT("----------\n"); ODP_PRINT(" handle %p\n", queue->s.handle); - ODP_PRINT(" index %" PRIu32 "\n", queue->s.index); + ODP_PRINT(" index %" PRIu32 "\n", queue_id); ODP_PRINT(" name %s\n", queue->s.name); ODP_PRINT(" enq mode %s\n", queue->s.param.enq_mode == ODP_QUEUE_OP_MT ? "ODP_QUEUE_OP_MT" : @@ -686,8 +687,11 @@ static void queue_print(odp_queue_t handle) "ODP_SCHED_SYNC_ATOMIC" : (queue->s.param.sched.sync == ODP_SCHED_SYNC_ORDERED ? "ODP_SCHED_SYNC_ORDERED" : "unknown"))); - ODP_PRINT(" priority %d\n", queue->s.param.sched.prio); - ODP_PRINT(" group %d\n", queue->s.param.sched.group); + prio = queue->s.param.sched.prio; + ODP_PRINT(" priority %i (%i in API)\n", max_prio - prio, prio); + ODP_PRINT(" group %i\n", queue->s.param.sched.group); + if (_odp_sched_id == _ODP_SCHED_ID_BASIC) + ODP_PRINT(" spread %i\n", _odp_sched_basic_get_spread(queue_id)); } if (queue->s.pktin.pktio != ODP_PKTIO_INVALID) { if (!odp_pktio_info(queue->s.pktin.pktio, &pktio_info)) @@ -744,11 +748,18 @@ static void queue_print_all(void) char type_c, enq_c, deq_c, order_c, sync_c; const int col_width = 24; int prio = 0; + int spr = 0; odp_schedule_sync_t sync = ODP_SCHED_SYNC_PARALLEL; + odp_schedule_group_t grp = ODP_SCHED_GROUP_INVALID; ODP_PRINT("\nList of all queues\n"); ODP_PRINT("------------------\n"); - ODP_PRINT(" idx %-*s type stat blk enq deq ord len max_len sync prio\n", col_width, "name"); + ODP_PRINT(" idx %-*s type stat blk enq deq ord len max_len sync prio grp", + col_width, "name"); + if (_odp_sched_id == _ODP_SCHED_ID_BASIC) + ODP_PRINT(" spr\n"); + else + ODP_PRINT("\n"); for (i = 0; i < CONFIG_MAX_QUEUES; i++) { queue_entry_t *queue = qentry_from_index(i); @@ -777,7 +788,10 @@ static void queue_print_all(void) len = ring_st_length(queue->s.ring_st); max_len = ring_st_max_length(queue->s.ring_st); prio = queue->s.param.sched.prio; + grp = queue->s.param.sched.group; sync = queue->s.param.sched.sync; + if (_odp_sched_id == _ODP_SCHED_ID_BASIC) + spr = _odp_sched_basic_get_spread(index); } else { len = ring_mpmc_length(queue->s.ring_mpmc); max_len = ring_mpmc_max_length(queue->s.ring_mpmc); @@ -811,7 +825,13 @@ static void queue_print_all(void) if (type == ODP_QUEUE_TYPE_SCHED) { sync_c = (sync == ODP_SCHED_SYNC_PARALLEL) ? 'P' : ((sync == ODP_SCHED_SYNC_ATOMIC) ? 'A' : 'O'); - ODP_PRINT(" %c %4i", sync_c, prio); + /* Print prio level matching odp_schedule_print() output */ + prio = odp_schedule_max_prio() - prio; + + ODP_PRINT(" %c %4i %3i", sync_c, prio, grp); + + if (_odp_sched_id == _ODP_SCHED_ID_BASIC) + ODP_PRINT(" %3i", spr); } ODP_PRINT("\n"); diff --git a/platform/linux-dpdk/odp_queue_eventdev.c b/platform/linux-dpdk/odp_queue_eventdev.c index 96baffa6f..0960c456e 100644 --- a/platform/linux-dpdk/odp_queue_eventdev.c +++ b/platform/linux-dpdk/odp_queue_eventdev.c @@ -528,7 +528,7 @@ static int queue_init_global(void) _odp_queue_inline_offset.context = offsetof(queue_entry_t, s.param.context); - shm = odp_shm_reserve("_odp_eventdev_gbl", + shm = odp_shm_reserve("_odp_queue_eventdev_global", sizeof(eventdev_global_t), ODP_CACHE_LINE_SIZE, 0); diff --git a/platform/linux-dpdk/odp_schedule_if.c b/platform/linux-dpdk/odp_schedule_if.c index 29d38b1fd..21f5fc85b 100644 --- a/platform/linux-dpdk/odp_schedule_if.c +++ b/platform/linux-dpdk/odp_schedule_if.c @@ -1,4 +1,5 @@ /* Copyright (c) 2018, Linaro Limited + * Copyright (c) 2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -11,6 +12,9 @@ #include <odp_debug_internal.h> #include <odp_global_data.h> +/* Required for _ODP_SCHED_ID_EVENTDEV */ +#include <odp_eventdev_internal.h> + #include <stdlib.h> #include <string.h> @@ -25,6 +29,7 @@ extern const schedule_api_t _odp_schedule_eventdev_api; const schedule_fn_t *_odp_sched_fn; const schedule_api_t *_odp_sched_api; +int _odp_sched_id; uint64_t odp_schedule_wait_time(uint64_t ns) { @@ -216,12 +221,15 @@ int _odp_schedule_init_global(void) ODP_PRINT("Using scheduler '%s'\n", sched); if (!strcmp(sched, "basic")) { + _odp_sched_id = _ODP_SCHED_ID_BASIC; _odp_sched_fn = &_odp_schedule_basic_fn; _odp_sched_api = &_odp_schedule_basic_api; } else if (!strcmp(sched, "sp")) { + _odp_sched_id = _ODP_SCHED_ID_SP; _odp_sched_fn = &_odp_schedule_sp_fn; _odp_sched_api = &_odp_schedule_sp_api; } else if (!strcmp(sched, "eventdev")) { + _odp_sched_id = _ODP_SCHED_ID_EVENTDEV; _odp_sched_fn = &_odp_schedule_eventdev_fn; _odp_sched_api = &_odp_schedule_eventdev_api; } else { diff --git a/platform/linux-dpdk/odp_shared_memory.c b/platform/linux-dpdk/odp_shared_memory.c index 4b1432a2f..645bb8847 100644 --- a/platform/linux-dpdk/odp_shared_memory.c +++ b/platform/linux-dpdk/odp_shared_memory.c @@ -1,4 +1,5 @@ /* Copyright (c) 2017-2018, Linaro Limited + * Copyright (c) 2021, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -25,9 +26,7 @@ #define SHM_MAX_ALIGN (0x80000000) #define SHM_BLOCK_NAME "%" PRIu64 "-%d-%s" - -ODP_STATIC_ASSERT(ODP_CONFIG_SHM_BLOCKS >= ODP_CONFIG_POOLS, - "ODP_CONFIG_SHM_BLOCKS < ODP_CONFIG_POOLS"); +#define SHM_MAX_NB_BLOCKS (CONFIG_INTERNAL_SHM_BLOCKS + CONFIG_SHM_BLOCKS) ODP_STATIC_ASSERT(ODP_SHM_NAME_LEN >= RTE_MEMZONE_NAMESIZE, "ODP_SHM_NAME_LEN < RTE_MEMZONE_NAMESIZE"); @@ -68,7 +67,7 @@ typedef struct { */ typedef struct { odp_spinlock_t lock; - shm_block_t block[ODP_CONFIG_SHM_BLOCKS]; + shm_block_t block[SHM_MAX_NB_BLOCKS]; } shm_table_t; static shm_table_t *shm_tbl; @@ -80,7 +79,7 @@ static odp_bool_t mz_name_used(const char *name) { int idx; - for (idx = 0; idx < ODP_CONFIG_SHM_BLOCKS; idx++) { + for (idx = 0; idx < SHM_MAX_NB_BLOCKS; idx++) { if (shm_tbl->block[idx].mz && strncmp(name, shm_tbl->block[idx].mz->name, RTE_MEMZONE_NAMESIZE) == 0) @@ -124,7 +123,7 @@ static int find_free_block(void) { int idx; - for (idx = 0; idx < ODP_CONFIG_SHM_BLOCKS; idx++) { + for (idx = 0; idx < SHM_MAX_NB_BLOCKS; idx++) { if (shm_tbl->block[idx].mz == NULL) return idx; } @@ -145,7 +144,7 @@ static inline odp_bool_t handle_is_valid(odp_shm_t shm) { int idx = handle_to_idx(shm); - if (idx < 0 || idx >= ODP_CONFIG_SHM_BLOCKS || + if (idx < 0 || idx >= SHM_MAX_NB_BLOCKS || shm_tbl->block[idx].mz == NULL) { ODP_ERR("Invalid odp_shm_t handle: %" PRIu64 "\n", odp_shm_to_u64(shm)); @@ -199,7 +198,7 @@ int _odp_shm_term_global(void) } /* Cleanup possibly non freed memory (and complain a bit) */ - for (idx = 0; idx < ODP_CONFIG_SHM_BLOCKS; idx++) { + for (idx = 0; idx < SHM_MAX_NB_BLOCKS; idx++) { block = &shm_tbl->block[idx]; if (block->mz) { ODP_ERR("block '%s' was never freed (cleaning up...)\n", @@ -224,7 +223,7 @@ int odp_shm_capability(odp_shm_capability_t *capa) { memset(capa, 0, sizeof(odp_shm_capability_t)); - capa->max_blocks = ODP_CONFIG_SHM_BLOCKS; + capa->max_blocks = CONFIG_SHM_BLOCKS; capa->max_size = 0; capa->max_align = SHM_MAX_ALIGN; @@ -357,7 +356,7 @@ odp_shm_t odp_shm_lookup(const char *name) odp_spinlock_lock(&shm_tbl->lock); - for (idx = 0; idx < ODP_CONFIG_SHM_BLOCKS; idx++) { + for (idx = 0; idx < SHM_MAX_NB_BLOCKS; idx++) { if (shm_tbl->block[idx].mz && strncmp(name, shm_tbl->block[idx].name, ODP_SHM_NAME_LEN) == 0) { @@ -425,7 +424,7 @@ void odp_shm_print_all(void) ODP_PRINT("\nShared memory blocks\n--------------------\n"); - for (idx = 0; idx < ODP_CONFIG_SHM_BLOCKS; idx++) { + for (idx = 0; idx < SHM_MAX_NB_BLOCKS; idx++) { block = &shm_tbl->block[idx]; if (block->mz == NULL) continue; diff --git a/platform/linux-dpdk/odp_system_info.c b/platform/linux-dpdk/odp_system_info.c index af07f387a..30fcc140b 100644 --- a/platform/linux-dpdk/odp_system_info.c +++ b/platform/linux-dpdk/odp_system_info.c @@ -515,7 +515,7 @@ void odp_sys_config_print(void) ODP_PRINT("CONFIG_PACKET_SEG_SIZE: %i\n", CONFIG_PACKET_SEG_SIZE); ODP_PRINT("CONFIG_PACKET_SEG_LEN_MIN: %i\n", CONFIG_PACKET_SEG_LEN_MIN); ODP_PRINT("CONFIG_PACKET_MAX_SEG_LEN: %i\n", CONFIG_PACKET_MAX_SEG_LEN); - ODP_PRINT("ODP_CONFIG_SHM_BLOCKS: %i\n", ODP_CONFIG_SHM_BLOCKS); + ODP_PRINT("CONFIG_SHM_BLOCKS: %i\n", CONFIG_SHM_BLOCKS); ODP_PRINT("CONFIG_BURST_SIZE: %i\n", CONFIG_BURST_SIZE); ODP_PRINT("CONFIG_POOL_MAX_NUM: %i\n", CONFIG_POOL_MAX_NUM); ODP_PRINT("\n"); diff --git a/platform/linux-dpdk/odp_thread.c b/platform/linux-dpdk/odp_thread.c index 59394b3e4..7ab41cf72 100644 --- a/platform/linux-dpdk/odp_thread.c +++ b/platform/linux-dpdk/odp_thread.c @@ -76,7 +76,7 @@ int _odp_thread_init_global(void) if (num_max > ODP_THREAD_COUNT_MAX) num_max = ODP_THREAD_COUNT_MAX; - shm = odp_shm_reserve("_odp_thread_globals", + shm = odp_shm_reserve("_odp_thread_global", sizeof(thread_globals_t), ODP_CACHE_LINE_SIZE, 0); |