Skip to content

Commit

Permalink
ethdev: reduce binary size for dummy queue
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
david-marchand committed Dec 5, 2024
1 parent 327c417 commit 90aad3b
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 34 deletions.
9 changes: 9 additions & 0 deletions lib/ethdev/ethdev_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
100 changes: 74 additions & 26 deletions lib/ethdev/ethdev_private.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
* Copyright(c) 2018 Gaëtan Rivet
*/

#include <stdlib.h>

#include <rte_debug.h>

#include "rte_ethdev.h"
Expand Down Expand Up @@ -187,35 +189,24 @@ 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,
__rte_unused struct rte_mbuf **rx_pkts,
__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;
}
Expand All @@ -229,36 +220,93 @@ 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;
}
rte_errno = ENOTSUP;
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,
},
};
Expand Down
3 changes: 3 additions & 0 deletions lib/ethdev/ethdev_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
8 changes: 0 additions & 8 deletions lib/ethdev/rte_ethdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 90aad3b

Please sign in to comment.