diff options
Diffstat (limited to 'platform/linux-dpdk')
-rw-r--r-- | platform/linux-dpdk/Makefile.am | 1 | ||||
l--------- | platform/linux-dpdk/include-abi/odp/api/abi/time_types.h | 1 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp/api/plat/packet_inline_types.h | 7 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp/api/plat/packet_inlines.h | 2 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp/api/plat/time_inlines.h | 7 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp_event_internal.h | 3 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp_packet_internal.h | 15 | ||||
-rw-r--r-- | platform/linux-dpdk/include/odp_packet_io_internal.h | 1 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_init.c | 23 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_packet.c | 36 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_packet_dpdk.c | 128 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_pool.c | 60 | ||||
-rw-r--r-- | platform/linux-dpdk/odp_timer.c | 93 |
13 files changed, 303 insertions, 74 deletions
diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am index 76e205212..252b34fb2 100644 --- a/platform/linux-dpdk/Makefile.am +++ b/platform/linux-dpdk/Makefile.am @@ -114,6 +114,7 @@ odpapiabiarchinclude_HEADERS += \ include-abi/odp/api/abi/thrmask.h \ include-abi/odp/api/abi/ticketlock.h \ include-abi/odp/api/abi/time.h \ + include-abi/odp/api/abi/time_types.h \ include-abi/odp/api/abi/timer.h \ include-abi/odp/api/abi/timer_types.h \ include-abi/odp/api/abi/traffic_mngr.h \ diff --git a/platform/linux-dpdk/include-abi/odp/api/abi/time_types.h b/platform/linux-dpdk/include-abi/odp/api/abi/time_types.h new file mode 120000 index 000000000..2f280c709 --- /dev/null +++ b/platform/linux-dpdk/include-abi/odp/api/abi/time_types.h @@ -0,0 +1 @@ +../../../../../linux-generic/include-abi/odp/api/abi/time_types.h
\ No newline at end of file diff --git a/platform/linux-dpdk/include/odp/api/plat/packet_inline_types.h b/platform/linux-dpdk/include/odp/api/plat/packet_inline_types.h index c6ede5d3a..5466ce58b 100644 --- a/platform/linux-dpdk/include/odp/api/plat/packet_inline_types.h +++ b/platform/linux-dpdk/include/odp/api/plat/packet_inline_types.h @@ -121,7 +121,7 @@ typedef union { uint32_t all_flags; struct { - uint32_t reserved1: 6; + uint32_t reserved1: 5; /* * Init flags @@ -140,6 +140,7 @@ typedef union { uint32_t l4_chksum: 1; /* L4 chksum override */ uint32_t ts_set: 1; /* Set Tx timestamp */ uint32_t tx_compl: 1; /* Tx completion event requested */ + uint32_t free_ctrl: 1; /* Don't free option */ uint32_t tx_aging: 1; /* Packet aging at Tx requested */ uint32_t shaper_len_adj: 8; /* Adjustment for traffic mgr */ @@ -157,8 +158,8 @@ typedef union { /* Flag groups */ struct { - uint32_t reserved2: 6; - uint32_t other: 19; /* All other flags */ + uint32_t reserved2: 5; + uint32_t other: 20; /* All other flags */ uint32_t error: 7; /* All error flags */ } all; diff --git a/platform/linux-dpdk/include/odp/api/plat/packet_inlines.h b/platform/linux-dpdk/include/odp/api/plat/packet_inlines.h index 4ae53c7b3..7b2764a05 100644 --- a/platform/linux-dpdk/include/odp/api/plat/packet_inlines.h +++ b/platform/linux-dpdk/include/odp/api/plat/packet_inlines.h @@ -22,7 +22,7 @@ extern "C" { #include <odp/api/hints.h> #include <odp/api/packet_types.h> #include <odp/api/pool_types.h> -#include <odp/api/time.h> +#include <odp/api/time_types.h> #include <odp/api/plat/debug_inlines.h> #include <odp/api/plat/event_validation_external.h> diff --git a/platform/linux-dpdk/include/odp/api/plat/time_inlines.h b/platform/linux-dpdk/include/odp/api/plat/time_inlines.h index 0ab2b37c0..4b1320300 100644 --- a/platform/linux-dpdk/include/odp/api/plat/time_inlines.h +++ b/platform/linux-dpdk/include/odp/api/plat/time_inlines.h @@ -1,5 +1,5 @@ /* Copyright (c) 2018, Linaro Limited - * Copyright (c) 2020-2022, Nokia + * Copyright (c) 2020-2023, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -8,13 +8,14 @@ #ifndef ODP_PLAT_TIME_INLINES_H_ #define ODP_PLAT_TIME_INLINES_H_ -#include <stdint.h> - #include <odp/api/align.h> #include <odp/api/hints.h> +#include <odp/api/time_types.h> #include <odp/api/abi/cpu_time.h> +#include <stdint.h> + /** @cond _ODP_HIDE_FROM_DOXYGEN_ */ #define _ODP_TIMESPEC_SIZE 16 diff --git a/platform/linux-dpdk/include/odp_event_internal.h b/platform/linux-dpdk/include/odp_event_internal.h index 6a707606a..cbe6d960b 100644 --- a/platform/linux-dpdk/include/odp_event_internal.h +++ b/platform/linux-dpdk/include/odp_event_internal.h @@ -46,6 +46,9 @@ typedef struct _odp_event_hdr_int_t { /* Event type. Maybe different than pool type (crypto compl event) */ int8_t event_type; + /* Event subtype */ + int8_t subtype; + /* Event flow id */ uint8_t flow_id; diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h index df4f2318e..37729b8f5 100644 --- a/platform/linux-dpdk/include/odp_packet_internal.h +++ b/platform/linux-dpdk/include/odp_packet_internal.h @@ -124,8 +124,10 @@ typedef struct ODP_ALIGNED_CACHE odp_packet_hdr_t { /* Common internal header */ _odp_event_hdr_int_t event_hdr; + /* Parser metadata */ packet_parser_t p; + /* Input interface */ odp_pktio_t input; /* Timestamp value */ @@ -162,9 +164,6 @@ typedef struct ODP_ALIGNED_CACHE odp_packet_hdr_t { /* LSO profile index */ uint8_t lso_profile_idx; - /* Event subtype */ - int8_t subtype; - union { /* Result for crypto packet op */ odp_crypto_packet_result_t crypto_op_result; @@ -215,7 +214,7 @@ static inline struct rte_mbuf *pkt_to_mbuf(odp_packet_t pkt) static inline void packet_subtype_set(odp_packet_t pkt, int ev) { - packet_hdr(pkt)->subtype = ev; + packet_hdr(pkt)->event_hdr.subtype = ev; } /** @@ -231,9 +230,7 @@ static inline void packet_init(odp_packet_hdr_t *pkt_hdr, odp_pktio_t input) pkt_hdr->p.l3_offset = ODP_PACKET_OFFSET_INVALID; pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID; - if (odp_unlikely(pkt_hdr->subtype != ODP_EVENT_PACKET_BASIC)) - pkt_hdr->subtype = ODP_EVENT_PACKET_BASIC; - + pkt_hdr->event_hdr.subtype = ODP_EVENT_PACKET_BASIC; pkt_hdr->input = input; } @@ -277,10 +274,10 @@ static inline void _odp_packet_copy_md(odp_packet_hdr_t *dst_hdr, odp_packet_hdr_t *src_hdr, odp_bool_t uarea_copy) { - const int8_t subtype = src_hdr->subtype; + const int8_t subtype = src_hdr->event_hdr.subtype; dst_hdr->input = src_hdr->input; - dst_hdr->subtype = subtype; + dst_hdr->event_hdr.subtype = subtype; dst_hdr->dst_queue = src_hdr->dst_queue; dst_hdr->cos = src_hdr->cos; dst_hdr->cls_mark = src_hdr->cls_mark; diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h b/platform/linux-dpdk/include/odp_packet_io_internal.h index 2efa52b67..ac22cff99 100644 --- a/platform/linux-dpdk/include/odp_packet_io_internal.h +++ b/platform/linux-dpdk/include/odp_packet_io_internal.h @@ -23,6 +23,7 @@ extern "C" { #include <odp/api/packet_io.h> #include <odp/api/spinlock.h> #include <odp/api/ticketlock.h> +#include <odp/api/time.h> #include <odp/api/plat/packet_io_inlines.h> diff --git a/platform/linux-dpdk/odp_init.c b/platform/linux-dpdk/odp_init.c index d35c63692..c7ae1ea47 100644 --- a/platform/linux-dpdk/odp_init.c +++ b/platform/linux-dpdk/odp_init.c @@ -26,6 +26,7 @@ #include <inttypes.h> #include <rte_config.h> +#include <rte_debug.h> #include <rte_eal.h> #include <rte_string_fns.h> @@ -872,6 +873,28 @@ int odp_term_local(void) return term_local(ALL_INIT); } +int odp_term_abnormal(odp_instance_t instance, uint64_t flags, void *data ODP_UNUSED) +{ + rte_dump_stack(); + + if (flags & ODP_TERM_FROM_SIGH) + /* Called from signal handler, not safe to terminate with local/global, + * return with failure as not able to perform all actions */ + return -1; + + if (odp_term_local() < 0) { + _ODP_ERR("ODP local terminate failed.\n"); + return -2; + } + + if (odp_term_global(instance) < 0) { + _ODP_ERR("ODP global terminate failed.\n"); + return -3; + } + + return 0; +} + void odp_log_thread_fn_set(odp_log_func_t func) { _odp_this_thread->log_fn = func; diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c index 06c6c36ad..95149118e 100644 --- a/platform/linux-dpdk/odp_packet.c +++ b/platform/linux-dpdk/odp_packet.c @@ -64,7 +64,7 @@ const _odp_packet_inline_offset_t _odp_packet_inline ODP_ALIGNED_CACHE = { .timestamp = offsetof(odp_packet_hdr_t, timestamp), .input_flags = offsetof(odp_packet_hdr_t, p.input_flags), .flags = offsetof(odp_packet_hdr_t, p.flags), - .subtype = offsetof(odp_packet_hdr_t, subtype), + .subtype = offsetof(odp_packet_hdr_t, event_hdr.subtype), .cls_mark = offsetof(odp_packet_hdr_t, cls_mark), .ipsec_ctx = offsetof(odp_packet_hdr_t, ipsec_ctx), .crypto_op = offsetof(odp_packet_hdr_t, crypto_op_result), @@ -1018,7 +1018,7 @@ void odp_packet_print(odp_packet_t pkt) odp_packet_to_u64(pkt)); len += _odp_snprint(&str[len], n - len, " pool index %u\n", pool->pool_idx); len += _odp_snprint(&str[len], n - len, " buf index %u\n", hdr->event_hdr.index); - len += _odp_snprint(&str[len], n - len, " ev subtype %i\n", hdr->subtype); + len += _odp_snprint(&str[len], n - len, " ev subtype %i\n", hdr->event_hdr.subtype); len += _odp_snprint(&str[len], n - len, " input_flags 0x%" PRIx64 "\n", hdr->p.input_flags.all); if (hdr->p.input_flags.all) { @@ -1766,7 +1766,7 @@ int odp_packet_tx_compl_request(odp_packet_t pkt, const odp_packet_tx_compl_opt_ { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - pkt_hdr->p.flags.tx_compl = opt->mode == ODP_PACKET_TX_COMPL_ALL ? 1 : 0; + pkt_hdr->p.flags.tx_compl = opt->mode == ODP_PACKET_TX_COMPL_EVENT ? 1 : 0; pkt_hdr->dst_queue = opt->queue; return 0; @@ -1801,6 +1801,34 @@ void *odp_packet_tx_compl_user_ptr(odp_packet_tx_compl_t tx_compl) return (void *)(uintptr_t)data->user_ptr; } +int odp_packet_tx_compl_done(odp_pktio_t pktio, uint32_t compl_id) +{ + (void)pktio; + (void)compl_id; + + return -1; +} + +void odp_packet_free_ctrl_set(odp_packet_t pkt, odp_packet_free_ctrl_t ctrl) +{ + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + + if (ctrl == ODP_PACKET_FREE_CTRL_DONT_FREE) + pkt_hdr->p.flags.free_ctrl = 1; + else + pkt_hdr->p.flags.free_ctrl = 0; +} + +odp_packet_free_ctrl_t odp_packet_free_ctrl(odp_packet_t pkt) +{ + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + + if (pkt_hdr->p.flags.free_ctrl) + return ODP_PACKET_FREE_CTRL_DONT_FREE; + + return ODP_PACKET_FREE_CTRL_DISABLED; +} + odp_packet_reass_status_t odp_packet_reass_status(odp_packet_t pkt) { (void)pkt; @@ -1903,7 +1931,7 @@ odp_packet_t odp_packet_reassemble(odp_pool_t pool_hdl, pkt_hdr->mb.data_off = headroom; /* Reset metadata */ - pkt_hdr->subtype = ODP_EVENT_PACKET_BASIC; + pkt_hdr->event_hdr.subtype = ODP_EVENT_PACKET_BASIC; pkt_hdr->input = ODP_PKTIO_INVALID; packet_parse_reset(pkt_hdr, 1); diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c index 238f733cd..c4fa3f0b7 100644 --- a/platform/linux-dpdk/odp_packet_dpdk.c +++ b/platform/linux-dpdk/odp_packet_dpdk.c @@ -127,6 +127,9 @@ typedef struct { typedef struct ODP_ALIGNED_CACHE { /* --- Fast path data --- */ + /* Function for mbuf to ODP packet conversion */ + int (*mbuf_to_pkt_fn)(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], uint16_t num); + /* DPDK port identifier */ uint16_t port_id; struct { @@ -187,6 +190,11 @@ extern void *pktio_entry_ptr[ODP_CONFIG_PKTIO_ENTRIES]; static uint32_t mtu_get_pkt_dpdk(pktio_entry_t *pktio_entry); +static inline int input_pkts(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], uint16_t num); + +static inline int input_pkts_minimal(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], + uint16_t num); + uint16_t _odp_dpdk_pktio_port_id(pktio_entry_t *pktio_entry) { const pkt_dpdk_t *pkt_dpdk = pkt_priv(pktio_entry); @@ -901,6 +909,12 @@ static int dpdk_start(pktio_entry_t *pktio_entry) } } + /* Use simpler function when packet parsing and classifying are not required */ + if (pktio_entry->parse_layer == ODP_PROTO_LAYER_NONE) + pkt_dpdk->mbuf_to_pkt_fn = input_pkts_minimal; + else + pkt_dpdk->mbuf_to_pkt_fn = input_pkts; + /* Start device */ ret = rte_eth_dev_start(port_id); if (ret < 0) { @@ -929,19 +943,60 @@ static inline void prefetch_pkt(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - odp_prefetch(&pkt_hdr->p); + odp_prefetch_store(&pkt_hdr->p); } -static inline int input_pkts(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], int num) +/** + * Input packets when packet parsing and classifier are disabled + */ +static inline int input_pkts_minimal(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], + uint16_t num) { uint16_t i; - uint16_t num_pkts = 0; - odp_pktin_config_opt_t pktin_cfg = pktio_entry->config.pktin; - odp_pktio_t input = pktio_entry->handle; odp_time_t ts_val; odp_time_t *ts = NULL; - uint16_t num_prefetch = RTE_MIN(num, NUM_RX_PREFETCH); + const uint8_t ts_ena = (pktio_entry->config.pktin.bit.ts_all || + pktio_entry->config.pktin.bit.ts_ptp); + const odp_pktio_t input = pktio_entry->handle; + const uint16_t num_prefetch = RTE_MIN(num, NUM_RX_PREFETCH); + + for (i = 0; i < num_prefetch; i++) + prefetch_pkt(pkt_table[i]); + + if (ts_ena) { + ts_val = odp_time_global(); + ts = &ts_val; + } + + for (i = 0; i < num; ++i) { + odp_packet_t pkt = pkt_table[i]; + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + + if (odp_likely(i + num_prefetch < num)) + prefetch_pkt(pkt_table[i + num_prefetch]); + + packet_init(pkt_hdr, input); + + packet_set_ts(pkt_hdr, ts); + } + + return num; +} + +/** + * input packets when packet parsing is required + */ +static inline int input_pkts(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], uint16_t num) +{ + uint16_t i; + uint16_t num_pkts = 0, num_cls = 0; + odp_time_t ts_val; + odp_time_t *ts = NULL; + const odp_pktin_config_opt_t pktin_cfg = pktio_entry->config.pktin; + const odp_pktio_t input = pktio_entry->handle; const odp_proto_layer_t layer = pktio_entry->parse_layer; + const int cls_enabled = pktio_cls_enabled(pktio_entry); + const uint16_t num_prefetch = RTE_MIN(num, NUM_RX_PREFETCH); for (i = 0; i < num_prefetch; i++) prefetch_pkt(pkt_table[i]); @@ -955,47 +1010,34 @@ static inline int input_pkts(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[ odp_packet_t pkt = pkt_table[i]; odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); struct rte_mbuf *mbuf = pkt_to_mbuf(pkt); + int ret; if (odp_likely(i + num_prefetch < num)) prefetch_pkt(pkt_table[i + num_prefetch]); packet_init(pkt_hdr, input); - if (layer != ODP_PROTO_LAYER_NONE) { - int ret; - - ret = _odp_dpdk_packet_parse_common(pkt_hdr, - rte_pktmbuf_mtod(mbuf, uint8_t *), - rte_pktmbuf_pkt_len(mbuf), - rte_pktmbuf_data_len(mbuf), - mbuf, layer, pktin_cfg); - if (odp_unlikely(ret)) { - odp_atomic_inc_u64(&pktio_entry->stats_extra.in_errors); + ret = _odp_dpdk_packet_parse_common(pkt_hdr, + rte_pktmbuf_mtod(mbuf, uint8_t *), + rte_pktmbuf_pkt_len(mbuf), + rte_pktmbuf_data_len(mbuf), + mbuf, layer, pktin_cfg); + if (odp_unlikely(ret)) { + odp_atomic_inc_u64(&pktio_entry->stats_extra.in_errors); - if (ret < 0) { - odp_packet_free(pkt); - continue; - } + if (ret < 0) { + odp_packet_free(pkt); + continue; } - - if (odp_unlikely(num_pkts != i)) - pkt_table[num_pkts] = pkt; } + packet_set_ts(pkt_hdr, ts); odp_prefetch(rte_pktmbuf_mtod(mbuf, char *)); - num_pkts++; - } - - if (pktio_cls_enabled(pktio_entry)) { - int success = 0; - for (i = 0; i < num_pkts; i++) { - odp_packet_t pkt = pkt_table[i]; + if (cls_enabled) { odp_pool_t new_pool; uint8_t *data = odp_packet_data(pkt); - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - int ret; ret = _odp_cls_classify_packet(pktio_entry, data, &new_pool, pkt_hdr); if (odp_unlikely(ret)) { @@ -1014,23 +1056,29 @@ static inline int input_pkts(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[ odp_atomic_inc_u64(&pktio_entry->stats_extra.in_discards); continue; } - pkt_table[i] = new_pkt; pkt = new_pkt; } - if (success != i) - pkt_table[success] = pkt; - ++success; + /* Enqueue packets directly to classifier destination queue */ + pkt_table[num_cls++] = pkt; + num_cls = _odp_cls_enq(pkt_table, num_cls, (i + 1 == num)); + } else { + pkt_table[num_pkts++] = pkt; } - num_pkts = success; } + /* Enqueue remaining classified packets */ + if (odp_unlikely(num_cls)) + _odp_cls_enq(pkt_table, num_cls, true); + return num_pkts; } int _odp_input_pkts(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[], int num) { - return input_pkts(pktio_entry, pkt_table, num); + pkt_dpdk_t * const pkt_dpdk = pkt_priv(pktio_entry); + + return pkt_dpdk->mbuf_to_pkt_fn(pktio_entry, pkt_table, num); } static int recv_pkt_dpdk(pktio_entry_t *pktio_entry, int index, @@ -1071,10 +1119,10 @@ static int recv_pkt_dpdk(pktio_entry_t *pktio_entry, int index, odp_ticketlock_unlock(&pkt_dpdk->rx_lock[index]); /* Packets may also me received through eventdev, so don't add any - * processing here. Instead, perform all processing in input_pkts() + * processing here. Instead, perform all processing in mbuf_to_pkt_fn() * which is also called by eventdev. */ if (nb_rx) - return input_pkts(pktio_entry, pkt_table, nb_rx); + return pkt_dpdk->mbuf_to_pkt_fn(pktio_entry, pkt_table, nb_rx); return 0; } diff --git a/platform/linux-dpdk/odp_pool.c b/platform/linux-dpdk/odp_pool.c index 9dd1a5ca2..83d75dd6c 100644 --- a/platform/linux-dpdk/odp_pool.c +++ b/platform/linux-dpdk/odp_pool.c @@ -823,6 +823,24 @@ int odp_buffer_alloc_multi(odp_pool_t pool_hdl, odp_buffer_t buf[], int num) return _odp_event_alloc_multi(pool, (_odp_event_hdr_t **)buf, num); } +static const char *get_short_type_str(odp_pool_type_t type) +{ + switch (type) { + case ODP_POOL_BUFFER: + return "B"; + case ODP_POOL_PACKET: + return "P"; + case ODP_POOL_TIMEOUT: + return "T"; + case ODP_POOL_VECTOR: + return "V"; + case ODP_POOL_DMA_COMPL: + return "D"; + default: + return "-"; + } +} + void odp_pool_print(odp_pool_t pool_hdl) { pool_t *pool = _odp_pool_entry(pool_hdl); @@ -837,8 +855,7 @@ void odp_pool_print_all(void) uint32_t elt_size, elt_len = 0; uint8_t type, ext; const int col_width = 24; - const char *name; - char type_c; + const char *name, *type_c; _ODP_PRINT("\nList of all pools\n"); _ODP_PRINT("-----------------\n"); @@ -868,12 +885,9 @@ void odp_pool_print_all(void) if (type == ODP_POOL_BUFFER || type == ODP_POOL_PACKET) elt_len = elt_size; - type_c = (type == ODP_POOL_BUFFER) ? 'B' : - (type == ODP_POOL_PACKET) ? 'P' : - (type == ODP_POOL_TIMEOUT) ? 'T' : - (type == ODP_POOL_VECTOR) ? 'V' : '-'; + type_c = get_short_type_str(pool->type_2); - _ODP_PRINT("%4u %-*s %c %6" PRIu64 " %6" PRIu32 " %6" PRIu32 " %8" PRIu32 " " + _ODP_PRINT("%4u %-*s %s %6" PRIu64 " %6" PRIu32 " %6" PRIu32 " %8" PRIu32 " " "%" PRIu8 "\n", index, col_width, name, type_c, available, tot, cache_size, elt_len, ext); } @@ -913,6 +927,7 @@ int odp_pool_info(odp_pool_t pool_hdl, odp_pool_info_t *info) } else if (pool->type_2 == ODP_POOL_DMA_COMPL) { info->dma_pool_param.num = pool->params.buf.num; + info->dma_pool_param.uarea_size = pool->params.buf.uarea_size; info->dma_pool_param.cache_size = pool->params.buf.cache_size; } else { @@ -1004,6 +1019,37 @@ int odp_pool_stats(odp_pool_t pool_hdl, odp_pool_stats_t *stats) return 0; } +int odp_pool_stats_selected(odp_pool_t pool_hdl, odp_pool_stats_selected_t *stats, + const odp_pool_stats_opt_t *opt) +{ + pool_t *pool; + + if (odp_unlikely(pool_hdl == ODP_POOL_INVALID)) { + _ODP_ERR("Invalid pool handle\n"); + return -1; + } + if (odp_unlikely(stats == NULL)) { + _ODP_ERR("Output buffer NULL\n"); + return -1; + } + if (odp_unlikely(opt == NULL)) { + _ODP_ERR("Pool counters NULL\n"); + return -1; + } + + pool = _odp_pool_entry(pool_hdl); + + if (odp_unlikely(opt->all & ~pool->params.stats.all)) { + _ODP_ERR("Trying to read disabled counter\n"); + return -1; + } + + if (opt->bit.available) + stats->available = rte_mempool_avail_count(pool->rte_mempool); + + return 0; +} + int odp_pool_stats_reset(odp_pool_t pool_hdl ODP_UNUSED) { return 0; diff --git a/platform/linux-dpdk/odp_timer.c b/platform/linux-dpdk/odp_timer.c index 1021a96cd..4056018ae 100644 --- a/platform/linux-dpdk/odp_timer.c +++ b/platform/linux-dpdk/odp_timer.c @@ -93,6 +93,9 @@ ODP_STATIC_ASSERT(MAX_TIMERS < MAX_TIMER_RING_SIZE, /* Maximum number of periodic timers per pool */ #define MAX_PERIODIC_TIMERS 100 +/* Periodic tick fractional part accumulator size */ +#define ACC_SIZE (1ull << 32) + typedef struct { odp_ticketlock_t lock; uint64_t tick; @@ -102,8 +105,13 @@ typedef struct { struct timer_pool_s *timer_pool; int state; uint32_t timer_idx; + /* Period of periodic timer in ticks, includes PERIODIC_CANCELLED flag. */ uint64_t periodic_ticks; + /* Periodic ticks fractional part. */ + uint32_t periodic_ticks_frac; + /* Periodic ticks fractional part accumulator. */ + uint32_t periodic_ticks_frac_acc; struct rte_timer rte_timer; @@ -509,14 +517,26 @@ int odp_timer_res_capability(odp_timer_clk_src_t clk_src, } if (res_capa->min_tmo) { - _ODP_ERR("Only res_ns or max_tmo based quaries supported\n"); + _ODP_ERR("Only res_ns or max_tmo based queries supported\n"); return -1; } if (res_capa->res_ns || res_capa->res_hz) { + if (res_capa->res_ns && res_capa->res_ns < MAX_RES_NS) { + _ODP_DBG("Timeout resolution capability (res_ns) exceeded\n"); + return -1; + } + if (res_capa->res_hz && res_capa->res_hz > MAX_RES_HZ) { + _ODP_DBG("Timeout resolution capability (res_hz) exceeded\n"); + return -1; + } res_capa->min_tmo = min_tmo; res_capa->max_tmo = MAX_TMO_NS; } else { /* max_tmo */ + if (res_capa->max_tmo > MAX_TMO_NS) { + _ODP_DBG("Maximum relative timeout capability (max_tmo) exceeded\n"); + return -1; + } res_capa->min_tmo = min_tmo; res_capa->res_ns = MAX_RES_NS; res_capa->res_hz = MAX_RES_HZ; @@ -787,6 +807,35 @@ uint64_t odp_timer_current_tick(odp_timer_pool_t tp) return rte_get_timer_cycles(); } +int odp_timer_sample_ticks(odp_timer_pool_t tp[], uint64_t tick[], uint64_t clk_count[], int num) +{ + uint64_t now; + int i; + + if (num <= 0 || num > MAX_TIMER_POOLS) { + _ODP_ERR("Bad number of timer pools: %i\n", num); + return -1; + } + + for (i = 0; i < num; i++) { + if (odp_unlikely(tp[i] == ODP_TIMER_POOL_INVALID)) { + _ODP_ERR("Invalid timer pool\n"); + return -1; + } + } + + now = rte_get_timer_cycles(); + + for (i = 0; i < num; i++) { + tick[i] = now; + + if (clk_count) + clk_count[i] = 0; + } + + return 0; +} + int odp_timer_pool_info(odp_timer_pool_t tp, odp_timer_pool_info_t *info) { @@ -1065,6 +1114,7 @@ int odp_timer_periodic_start(odp_timer_t timer_hdl, timer_pool_t *tp = timer->timer_pool; uint64_t multiplier = start_param->freq_multiplier; double freq = multiplier * tp->base_freq; + double period_ns_dbl; int absolute; int ret; @@ -1083,13 +1133,18 @@ int odp_timer_periodic_start(odp_timer_t timer_hdl, return ODP_TIMER_FAIL; } - period_ns = (uint64_t)((double)ODP_TIME_SEC_IN_NS / freq); + period_ns_dbl = (double)ODP_TIME_SEC_IN_NS / freq; + period_ns = period_ns_dbl; + if (period_ns == 0) { _ODP_ERR("Too high periodic timer frequency: %f\n", freq); return ODP_TIMER_FAIL; } timer->periodic_ticks = odp_timer_ns_to_tick(timer_pool_to_hdl(tp), period_ns); + timer->periodic_ticks_frac = (period_ns_dbl - period_ns) * ACC_SIZE; + timer->periodic_ticks_frac_acc = 0; + first_tick = timer->periodic_ticks; absolute = 0; @@ -1113,7 +1168,7 @@ int odp_timer_periodic_start(odp_timer_t timer_hdl, int odp_timer_periodic_ack(odp_timer_t timer_hdl, odp_event_t tmo_ev) { - uint64_t abs_tick; + uint64_t abs_tick, acc; odp_timeout_t tmo = odp_timeout_from_event(tmo_ev); timer_entry_t *timer = timer_from_hdl(timer_hdl); odp_timeout_hdr_t *timeout_hdr; @@ -1129,6 +1184,15 @@ int odp_timer_periodic_ack(odp_timer_t timer_hdl, odp_event_t tmo_ev) if (odp_unlikely(abs_tick == PERIODIC_CANCELLED)) return 2; + acc = (uint64_t)timer->periodic_ticks_frac_acc + (uint64_t)timer->periodic_ticks_frac; + + if (acc >= ACC_SIZE) { + abs_tick++; + acc -= ACC_SIZE; + } + + timer->periodic_ticks_frac_acc = acc; + timeout_hdr = timeout_to_hdr(tmo); abs_tick += timeout_hdr->expiration; timeout_hdr->expiration = abs_tick; @@ -1156,14 +1220,19 @@ int odp_timer_cancel(odp_timer_t timer_hdl, odp_event_t *tmo_ev) odp_ticketlock_lock(&timer->lock); if (odp_unlikely(timer->state < TICKING)) { + int state = timer->state; + odp_ticketlock_unlock(&timer->lock); - return -1; + + if (state == EXPIRED) + return ODP_TIMER_TOO_NEAR; + return ODP_TIMER_FAIL; } if (odp_unlikely(timer_global->ops.stop(&timer->rte_timer))) { /* Another core runs timer callback function. */ odp_ticketlock_unlock(&timer->lock); - return -1; + return ODP_TIMER_TOO_NEAR; } *tmo_ev = timer->tmo_event; @@ -1171,7 +1240,7 @@ int odp_timer_cancel(odp_timer_t timer_hdl, odp_event_t *tmo_ev) timer->state = NOT_TICKING; odp_ticketlock_unlock(&timer->lock); - return 0; + return ODP_TIMER_SUCCESS; } int odp_timer_periodic_cancel(odp_timer_t timer_hdl) @@ -1228,8 +1297,14 @@ uint64_t odp_timeout_to_u64(odp_timeout_t tmo) int odp_timeout_fresh(odp_timeout_t tmo) { + timer_entry_t *timer; odp_timeout_hdr_t *timeout_hdr = timeout_to_hdr(tmo); - timer_entry_t *timer = timer_from_hdl(timeout_hdr->timer); + + /* Timeout not connected to a timer */ + if (odp_unlikely(timeout_hdr->timer == ODP_TIMER_INVALID)) + return 0; + + timer = timer_from_hdl(timeout_hdr->timer); if (timer->timer_pool->periodic) return timer->periodic_ticks != PERIODIC_CANCELLED; @@ -1240,6 +1315,7 @@ int odp_timeout_fresh(odp_timeout_t tmo) odp_timeout_t odp_timeout_alloc(odp_pool_t pool_hdl) { + odp_timeout_hdr_t *timeout_hdr; odp_event_t event; pool_t *pool; @@ -1253,6 +1329,9 @@ odp_timeout_t odp_timeout_alloc(odp_pool_t pool_hdl) if (odp_unlikely(event == ODP_EVENT_INVALID)) return ODP_TIMEOUT_INVALID; + timeout_hdr = timeout_to_hdr(odp_timeout_from_event(event)); + timeout_hdr->timer = ODP_TIMER_INVALID; + return odp_timeout_from_event(event); } |