From 90aad3bc4df1cdb69c26a850afd5a1f66516e0ca Mon Sep 17 00:00:00 2001 From: David Marchand Date: Fri, 3 Feb 2023 15:24:47 +0100 Subject: [PATCH] ethdev: reduce binary size for dummy queue Rather than have a static array (which size depends on RTE_MAX_ETHPORTS * RTE_MAX_QUEUES_PER_PORT), allocate dummy queues on the first time a port is allocated. With default configuration, this consumed 256kB of .bss for 32 ports. Signed-off-by: David Marchand --- lib/ethdev/ethdev_driver.c | 9 ++++ lib/ethdev/ethdev_private.c | 100 ++++++++++++++++++++++++++---------- lib/ethdev/ethdev_private.h | 3 ++ lib/ethdev/rte_ethdev.c | 8 --- 4 files changed, 86 insertions(+), 34 deletions(-) diff --git a/lib/ethdev/ethdev_driver.c b/lib/ethdev/ethdev_driver.c index 9afef064313..7f5328fa3c4 100644 --- a/lib/ethdev/ethdev_driver.c +++ b/lib/ethdev/ethdev_driver.c @@ -113,6 +113,11 @@ rte_eth_dev_allocate(const char *name) } eth_dev = eth_dev_get(port_id); + if (eth_dev_fp_ops_init(rte_eth_fp_ops + port_id) != 0) { + RTE_ETHDEV_LOG_LINE(ERR, "Failed to initialise rte_eth_fp_ops"); + eth_dev = NULL; + goto unlock; + } eth_dev->flow_fp_ops = &rte_flow_fp_default_ops; strlcpy(eth_dev->data->name, name, sizeof(eth_dev->data->name)); eth_dev->data->port_id = port_id; @@ -173,6 +178,10 @@ rte_eth_dev_attach_secondary(const char *name) } else { eth_dev = eth_dev_get(i); RTE_ASSERT(eth_dev->data->port_id == i); + if (eth_dev_fp_ops_init(rte_eth_fp_ops + i) != 0) { + RTE_ETHDEV_LOG_LINE(ERR, "Failed to initialise rte_eth_fp_ops"); + eth_dev = NULL; + } } unlock: diff --git a/lib/ethdev/ethdev_private.c b/lib/ethdev/ethdev_private.c index eed8c787477..13c33909019 100644 --- a/lib/ethdev/ethdev_private.c +++ b/lib/ethdev/ethdev_private.c @@ -2,6 +2,8 @@ * Copyright(c) 2018 Gaƫtan Rivet */ +#include + #include #include "rte_ethdev.h" @@ -187,22 +189,13 @@ rte_eth_devargs_parse_representor_ports(char *str, void *data) } struct dummy_queue { + uint16_t port_id; bool rx_warn_once; bool tx_warn_once; }; -static struct dummy_queue *dummy_queues_array[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; -static struct dummy_queue per_port_queues[RTE_MAX_ETHPORTS]; -RTE_INIT(dummy_queue_init) -{ - uint16_t port_id; - for (port_id = 0; port_id < RTE_DIM(per_port_queues); port_id++) { - unsigned int q; - - for (q = 0; q < RTE_DIM(dummy_queues_array[port_id]); q++) - dummy_queues_array[port_id][q] = &per_port_queues[port_id]; - } -} +static struct dummy_queue ***dummy_queues_array; +static unsigned int dummy_queues_array_count; static uint16_t dummy_eth_rx_burst(void *rxq, @@ -210,12 +203,10 @@ dummy_eth_rx_burst(void *rxq, __rte_unused uint16_t nb_pkts) { struct dummy_queue *queue = rxq; - uintptr_t port_id; - port_id = queue - per_port_queues; - if (port_id < RTE_DIM(per_port_queues) && !queue->rx_warn_once) { - RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called rx_pkt_burst for not ready port %"PRIuPTR, - rte_lcore_id(), port_id); + if (!queue->rx_warn_once) { + RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called rx_pkt_burst for not ready port %"PRIu16, + rte_lcore_id(), queue->port_id); rte_dump_stack(); queue->rx_warn_once = true; } @@ -229,12 +220,10 @@ dummy_eth_tx_burst(void *txq, __rte_unused uint16_t nb_pkts) { struct dummy_queue *queue = txq; - uintptr_t port_id; - port_id = queue - per_port_queues; - if (port_id < RTE_DIM(per_port_queues) && !queue->tx_warn_once) { - RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called tx_pkt_burst for not ready port %"PRIuPTR, - rte_lcore_id(), port_id); + if (!queue->tx_warn_once) { + RTE_ETHDEV_LOG_LINE(ERR, "lcore %u called tx_pkt_burst for not ready port %"PRIu16, + rte_lcore_id(), queue->port_id); rte_dump_stack(); queue->tx_warn_once = true; } @@ -242,23 +231,82 @@ dummy_eth_tx_burst(void *txq, return 0; } +int +eth_dev_fp_ops_init(struct rte_eth_fp_ops *fpo) +{ + uintptr_t port_id = fpo - rte_eth_fp_ops; + + if (port_id >= dummy_queues_array_count) { + typeof(dummy_queues_array) new_array; + unsigned int p; + + new_array = realloc(dummy_queues_array, + sizeof(*dummy_queues_array) * (port_id + 1)); + if (new_array == NULL) + return -ENOMEM; + dummy_queues_array = new_array; + for (p = dummy_queues_array_count; p < port_id + 1; p++) + dummy_queues_array[p] = NULL; + dummy_queues_array_count = port_id + 1; + } + + if (dummy_queues_array[port_id] == NULL) { + struct dummy_queue **queues; + struct dummy_queue *queue; + unsigned int q; + + queue = malloc(sizeof(*queue)); + queues = calloc(RTE_MAX_QUEUES_PER_PORT, sizeof(*queues)); + if (queue == NULL || queues == NULL) { + free(queue); + free(queues); + return -ENOMEM; + } + + queue->port_id = port_id; + /* All queue pointers refer to the same queue object */ + for (q = 0; q < RTE_MAX_QUEUES_PER_PORT; q++) + queues[q] = queue; + dummy_queues_array[port_id] = queues; + } + + eth_dev_fp_ops_reset(fpo); + + return 0; +} + +RTE_FINI(dummy_queue_cleanup) +{ + unsigned int port_id; + + for (port_id = 0; port_id < dummy_queues_array_count; port_id++) { + if (dummy_queues_array[port_id][0] != NULL) + free(dummy_queues_array[port_id][0]); + free(dummy_queues_array[port_id]); + } + free(dummy_queues_array); + dummy_queues_array = NULL; + dummy_queues_array_count = 0; +} + void eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo) { static RTE_ATOMIC(void *) dummy_data[RTE_MAX_QUEUES_PER_PORT]; uintptr_t port_id = fpo - rte_eth_fp_ops; - per_port_queues[port_id].rx_warn_once = false; - per_port_queues[port_id].tx_warn_once = false; + /* All queue pointers refer to the same queue object */ + dummy_queues_array[port_id][0]->rx_warn_once = false; + dummy_queues_array[port_id][0]->tx_warn_once = false; *fpo = (struct rte_eth_fp_ops) { .rx_pkt_burst = dummy_eth_rx_burst, .tx_pkt_burst = dummy_eth_tx_burst, .rxq = { - .data = (void **)&dummy_queues_array[port_id], + .data = (void **)dummy_queues_array[port_id], .clbk = dummy_data, }, .txq = { - .data = (void **)&dummy_queues_array[port_id], + .data = (void **)dummy_queues_array[port_id], .clbk = dummy_data, }, }; diff --git a/lib/ethdev/ethdev_private.h b/lib/ethdev/ethdev_private.h index 0d36b9c30f7..c714e88f09d 100644 --- a/lib/ethdev/ethdev_private.h +++ b/lib/ethdev/ethdev_private.h @@ -61,6 +61,9 @@ eth_find_device(const struct rte_eth_dev *_start, rte_eth_cmp_t cmp, /* Parse devargs value for representor parameter. */ int rte_eth_devargs_parse_representor_ports(char *str, void *data); +/* allocate and initialise rte_eth_fp_ops internals for one port */ +int eth_dev_fp_ops_init(struct rte_eth_fp_ops *fpo); + /* reset eth fast-path API to dummy values */ void eth_dev_fp_ops_reset(struct rte_eth_fp_ops *fpo); diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c index 6413c54e3b3..8ec2a138159 100644 --- a/lib/ethdev/rte_ethdev.c +++ b/lib/ethdev/rte_ethdev.c @@ -5502,14 +5502,6 @@ int rte_eth_rx_avail_thresh_query(uint16_t port_id, uint16_t *queue_id, return ret; } -RTE_INIT(eth_dev_init_fp_ops) -{ - uint32_t i; - - for (i = 0; i != RTE_DIM(rte_eth_fp_ops); i++) - eth_dev_fp_ops_reset(rte_eth_fp_ops + i); -} - RTE_INIT(eth_dev_init_cb_lists) { uint16_t i;