diff options
author | Tuomas Taipale <tuomas.taipale@nokia.com> | 2022-05-24 12:51:50 +0000 |
---|---|---|
committer | Petri Savolainen <petri.savolainen@nokia.com> | 2022-06-01 17:02:29 +0300 |
commit | e38f5278454b11b628e3357bc1606630e509eb6f (patch) | |
tree | e6814cf2f7dd92407928fc8d6c4c2ce590c9d140 | |
parent | f9e00911f199e8ab8c28dc17954a31058ec2ede6 (diff) |
linux-gen: socket_xdp: make RX and TX descriptor counts configurable
Make RX and TX descriptor counts configurable via linux-gen
configuration file. Current defaults are a good guess, but adjusting
them may (or may not) improve performance in some environments depending
on NIC configuration.
Signed-off-by: Tuomas Taipale <tuomas.taipale@nokia.com>
Reviewed-by: Matias Elo <matias.elo@nokia.com>
-rw-r--r-- | config/odp-linux-generic.conf | 13 | ||||
-rw-r--r-- | platform/linux-generic/m4/odp_libconfig.m4 | 2 | ||||
-rw-r--r-- | platform/linux-generic/pktio/socket_xdp.c | 146 | ||||
-rw-r--r-- | platform/linux-generic/test/inline-timer.conf | 2 | ||||
-rw-r--r-- | platform/linux-generic/test/packet_align.conf | 2 | ||||
-rw-r--r-- | platform/linux-generic/test/process-mode.conf | 2 | ||||
-rw-r--r-- | platform/linux-generic/test/sched-basic.conf | 2 |
7 files changed, 111 insertions, 58 deletions
diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf index 9534d2a5d..9c5e85242 100644 --- a/config/odp-linux-generic.conf +++ b/config/odp-linux-generic.conf @@ -16,7 +16,7 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.20" +config_file_version = "0.1.21" # System options system: { @@ -149,6 +149,17 @@ pktio_netmap: { } } +# XDP pktio options +pktio_xdp: { + # Number of RX and TX descriptors to be reserved for AF_XDP socket + # memory. Adjusting these may improve performance depending on NIC ring + # configuration. In zero-copy mode, packet pools used as pktio pools + # need to be large enough to accommodate RX and TX descriptors of every + # pktio queue. Values must be a power of two. + num_rx_desc = 1024 + num_tx_desc = 1024 +} + queue_basic: { # Maximum queue size. Value must be a power of two. max_queue_size = 8192 diff --git a/platform/linux-generic/m4/odp_libconfig.m4 b/platform/linux-generic/m4/odp_libconfig.m4 index ab4994d61..886cc07e8 100644 --- a/platform/linux-generic/m4/odp_libconfig.m4 +++ b/platform/linux-generic/m4/odp_libconfig.m4 @@ -3,7 +3,7 @@ ########################################################################## m4_define([_odp_config_version_generation], [0]) m4_define([_odp_config_version_major], [1]) -m4_define([_odp_config_version_minor], [20]) +m4_define([_odp_config_version_minor], [21]) m4_define([_odp_config_version], [_odp_config_version_generation._odp_config_version_major._odp_config_version_minor]) diff --git a/platform/linux-generic/pktio/socket_xdp.c b/platform/linux-generic/pktio/socket_xdp.c index e0667bc95..3bb41a682 100644 --- a/platform/linux-generic/pktio/socket_xdp.c +++ b/platform/linux-generic/pktio/socket_xdp.c @@ -22,6 +22,7 @@ #include <odp_parse_internal.h> #include <odp_classification_internal.h> #include <odp_socket_common.h> +#include <odp_libconfig_internal.h> #include <string.h> #include <errno.h> @@ -35,11 +36,14 @@ #include <xdp/xsk.h> -#define NUM_XDP_DESCS 1024U +#define NUM_DESCS_DEFAULT 1024U #define MIN_FRAME_SIZE 2048U #define IF_DELIM " " #define Q_DELIM ':' +#define CONF_BASE_STR "pktio_xdp" +#define RX_DESCS_STR "num_rx_desc" +#define TX_DESCS_STR "num_tx_desc" enum { RX_PKT_ALLOC_ERR, @@ -62,6 +66,8 @@ typedef struct { struct xsk_ring_cons compl_q; struct xsk_umem *umem; pool_t *pool; + int num_rx_desc; + int num_tx_desc; } xdp_umem_info_t; typedef struct { @@ -85,6 +91,7 @@ typedef struct { int helper_sock; uint32_t mtu; uint32_t max_mtu; + uint32_t bind_q; odp_bool_t lockless_rx; odp_bool_t lockless_tx; } xdp_sock_info_t; @@ -135,6 +142,47 @@ static int sock_xdp_stats_reset(pktio_entry_t *pktio_entry) return 0; } +static uint32_t get_bind_queue_index(const char *devname) +{ + const char *param = getenv("ODP_PKTIO_XDP_PARAMS"); + char *tmp_str; + char *tmp; + char *if_str; + int idx = 0; + + if (param == NULL) + goto out; + + tmp_str = strdup(param); + + if (tmp_str == NULL) + goto out; + + tmp = strtok(tmp_str, IF_DELIM); + + if (tmp == NULL) + goto out_str; + + while (tmp) { + if_str = strchr(tmp, Q_DELIM); + + if (if_str != NULL && if_str != &tmp[strlen(tmp) - 1U]) { + if (strncmp(devname, tmp, (uint64_t)(uintptr_t)(if_str - tmp)) == 0) { + idx = _ODP_MAX(atoi(++if_str), 0); + break; + } + } + + tmp = strtok(NULL, IF_DELIM); + } + +out_str: + free(tmp_str); + +out: + return idx; +} + static int sock_xdp_open(odp_pktio_t pktio, pktio_entry_t *pktio_entry, const char *devname, odp_pool_t pool_hdl) { @@ -174,6 +222,13 @@ static int sock_xdp_open(odp_pktio_t pktio, pktio_entry_t *pktio_entry, const ch odp_ticketlock_init(&priv->qs[i].tx_lock); } + priv->bind_q = get_bind_queue_index(pktio_entry->s.name); + + ODP_DBG("Socket xdp interface (%s):\n", pktio_entry->s.name); + ODP_DBG(" num_rx_desc: %d\n", priv->umem_info->num_rx_desc); + ODP_DBG(" num_tx_desc: %d\n", priv->umem_info->num_tx_desc); + ODP_DBG(" starting bind queue: %u\n", priv->bind_q); + return 0; mtu_err: @@ -543,7 +598,7 @@ static int sock_xdp_send(pktio_entry_t *pktio_entry, int index, const odp_packet uint8_t *base_addr; odp_packet_t pkt; odp_packet_hdr_t *pkt_hdr; - uint32_t start_idx, sent = 0U; + uint32_t tx_descs, start_idx, sent = 0U; uint64_t octets = 0U; if (odp_unlikely(num == 0)) @@ -560,6 +615,7 @@ static int sock_xdp_send(pktio_entry_t *pktio_entry, int index, const odp_packet pktio_idx = priv->pktio_idx; tx = &sock->tx; base_addr = priv->umem_info->pool->base_addr; + tx_descs = priv->umem_info->num_tx_desc; for (i = 0; i < num; ++i) { pkt = ODP_PACKET_INVALID; @@ -579,7 +635,7 @@ static int sock_xdp_send(pktio_entry_t *pktio_entry, int index, const odp_packet } if (xsk_ring_prod__reserve(tx, seg_cnt, &start_idx) == 0U) { - handle_pending_tx(sock, base_addr, NUM_XDP_DESCS); + handle_pending_tx(sock, base_addr, tx_descs); if (xsk_ring_prod__reserve(tx, seg_cnt, &start_idx) == 0U) { if (pkt != ODP_PACKET_INVALID) @@ -600,7 +656,7 @@ static int sock_xdp_send(pktio_entry_t *pktio_entry, int index, const odp_packet } xsk_ring_prod__submit(tx, sent); - handle_pending_tx(sock, base_addr, NUM_XDP_DESCS); + handle_pending_tx(sock, base_addr, tx_descs); sock->qo_stats.octets += octets; sock->qo_stats.packets += i; @@ -735,56 +791,15 @@ static int sock_xdp_input_queues_config(pktio_entry_t *pktio_entry, return 0; } -static void fill_socket_config(struct xsk_socket_config *config) +static void fill_socket_config(struct xsk_socket_config *config, xdp_umem_info_t *umem_info) { - config->rx_size = NUM_XDP_DESCS; - config->tx_size = NUM_XDP_DESCS; + config->rx_size = umem_info->num_rx_desc; + config->tx_size = umem_info->num_tx_desc; config->libxdp_flags = 0U; config->xdp_flags = 0U; config->bind_flags = XDP_ZEROCOPY; /* TODO: XDP_COPY */ } -static uint32_t get_bind_queue_index(const char *devname) -{ - const char *param = getenv("ODP_PKTIO_XDP_PARAMS"); - char *tmp_str; - char *tmp; - char *if_str; - int idx = 0; - - if (param == NULL) - goto out; - - tmp_str = strdup(param); - - if (tmp_str == NULL) - goto out; - - tmp = strtok(tmp_str, IF_DELIM); - - if (tmp == NULL) - goto out_str; - - while (tmp) { - if_str = strchr(tmp, Q_DELIM); - - if (if_str != NULL && if_str != &tmp[strlen(tmp) - 1U]) { - if (strncmp(devname, tmp, (uint64_t)(uintptr_t)(if_str - tmp)) == 0) { - idx = _ODP_MAX(atoi(++if_str), 0); - break; - } - } - - tmp = strtok(NULL, IF_DELIM); - } - -out_str: - free(tmp_str); - -out: - return idx; -} - static int sock_xdp_output_queues_config(pktio_entry_t *pktio_entry, const odp_pktout_queue_param_t *param) { @@ -797,8 +812,8 @@ static int sock_xdp_output_queues_config(pktio_entry_t *pktio_entry, int ret; priv->lockless_tx = param->op_mode == ODP_PKTIO_OP_MT_UNSAFE; - fill_socket_config(&config); - bind_q = get_bind_queue_index(devname); + fill_socket_config(&config, priv->umem_info); + bind_q = priv->bind_q; umem = priv->umem_info->umem; for (i = 0U; i < param->num_queues; ++i) { @@ -906,16 +921,43 @@ static void sock_xdp_adjust_block_size(uint8_t *data ODP_UNUSED, uint32_t *block *block_size = _ODP_MAX(size, MIN_FRAME_SIZE); } +static void parse_options(xdp_umem_info_t *umem_info) +{ + if (!_odp_libconfig_lookup_ext_int(CONF_BASE_STR, NULL, RX_DESCS_STR, + &umem_info->num_rx_desc) || + !_odp_libconfig_lookup_ext_int(CONF_BASE_STR, NULL, TX_DESCS_STR, + &umem_info->num_tx_desc)) { + ODP_ERR("Unable to parse xdp descriptor configuration, using defaults (%d).\n", + NUM_DESCS_DEFAULT); + goto defaults; + } + + if (umem_info->num_rx_desc <= 0 || umem_info->num_tx_desc <= 0 || + !_ODP_CHECK_IS_POWER2(umem_info->num_rx_desc) || + !_ODP_CHECK_IS_POWER2(umem_info->num_tx_desc)) { + ODP_ERR("Invalid xdp descriptor configuration, using defaults (%d).\n", + NUM_DESCS_DEFAULT); + goto defaults; + } + + return; + +defaults: + umem_info->num_rx_desc = NUM_DESCS_DEFAULT; + umem_info->num_tx_desc = NUM_DESCS_DEFAULT; +} + static int sock_xdp_umem_create(uint8_t *data, pool_t *pool) { struct xsk_umem_config cfg; xdp_umem_info_t *umem_info = (xdp_umem_info_t *)data; + parse_options(umem_info); umem_info->pool = pool; /* Fill queue size is recommended to be >= HW RX ring size + AF_XDP RX * ring size, so use size twice the size of AF_XDP RX ring. */ - cfg.fill_size = NUM_XDP_DESCS * 2U; /* TODO: num descs vs pool size */ - cfg.comp_size = NUM_XDP_DESCS; + cfg.fill_size = umem_info->num_rx_desc * 2U; + cfg.comp_size = umem_info->num_tx_desc; cfg.frame_size = pool->block_size; cfg.frame_headroom = sizeof(odp_packet_hdr_t) + pool->headroom; cfg.flags = XDP_UMEM_UNALIGNED_CHUNK_FLAG; diff --git a/platform/linux-generic/test/inline-timer.conf b/platform/linux-generic/test/inline-timer.conf index 2ade68c32..c7379e38a 100644 --- a/platform/linux-generic/test/inline-timer.conf +++ b/platform/linux-generic/test/inline-timer.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.20" +config_file_version = "0.1.21" timer: { # Enable inline timer implementation diff --git a/platform/linux-generic/test/packet_align.conf b/platform/linux-generic/test/packet_align.conf index f0370c7a2..433899017 100644 --- a/platform/linux-generic/test/packet_align.conf +++ b/platform/linux-generic/test/packet_align.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.20" +config_file_version = "0.1.21" pool: { pkt: { diff --git a/platform/linux-generic/test/process-mode.conf b/platform/linux-generic/test/process-mode.conf index 3ec28dce9..a36c9fc3d 100644 --- a/platform/linux-generic/test/process-mode.conf +++ b/platform/linux-generic/test/process-mode.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.20" +config_file_version = "0.1.21" # Shared memory options shm: { diff --git a/platform/linux-generic/test/sched-basic.conf b/platform/linux-generic/test/sched-basic.conf index 25e8b33e0..16654595b 100644 --- a/platform/linux-generic/test/sched-basic.conf +++ b/platform/linux-generic/test/sched-basic.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.20" +config_file_version = "0.1.21" # Test scheduler with an odd spread value and without dynamic load balance sched_basic: { |