dpdk: scale mempool size to the number of bond members

DPDK interface which were added to bond and had auto-calculated
mempool size didn't have enough space as the configured
descriptors and the derived mempool only considered one interface
per YAML node entry.

DPDK Bonding PMD allows for multiple interface to cooperate and
therefore, needs more space.

Ticket: 8216
(cherry picked from commit ecd15a6c7e)
pull/14981/head
Lukas Sismis 2 months ago committed by Victor Julien
parent 0c54932a4b
commit 4e0092280e

@ -81,7 +81,8 @@ static int ConfigSetThreads(DPDKIfaceConfig *iconf, const char *entry_str);
static int ConfigSetRxQueues(DPDKIfaceConfig *iconf, uint16_t nb_queues, uint16_t max_queues);
static int ConfigSetTxQueues(
DPDKIfaceConfig *iconf, uint16_t nb_queues, uint16_t max_queues, bool iface_sends_pkts);
static int ConfigSetMempoolSize(DPDKIfaceConfig *iconf, const char *entry_str);
static int ConfigSetMempoolSize(
DPDKIfaceConfig *iconf, const char *entry_str, const struct rte_eth_dev_info *dev_info);
static int ConfigSetMempoolCacheSize(DPDKIfaceConfig *iconf, const char *entry_str);
static int ConfigSetRxDescriptors(DPDKIfaceConfig *iconf, const char *entry_str, uint16_t max_desc);
static int ConfigSetTxDescriptors(
@ -530,16 +531,23 @@ static int ConfigSetTxQueues(
}
static uint32_t MempoolSizeCalculate(
uint32_t rx_queues, uint32_t rx_desc, uint32_t tx_queues, uint32_t tx_desc)
const DPDKIfaceConfig *iconf, const struct rte_eth_dev_info *dev_info)
{
uint32_t sz = rx_queues * rx_desc + tx_queues * tx_desc;
if (!tx_queues || !tx_desc)
uint32_t sz = iconf->nb_rx_queues * iconf->nb_rx_desc + iconf->nb_tx_queues * iconf->nb_tx_desc;
if (!iconf->nb_tx_queues || !iconf->nb_tx_desc)
sz *= 2; // double to have enough space for RX descriptors
if (dev_info != NULL) {
if (strcmp(dev_info->driver_name, "net_bonding") == 0) {
sz = BondingMempoolSizeCalculate(iconf->port_id, dev_info, sz);
}
}
return sz;
}
static int ConfigSetMempoolSize(DPDKIfaceConfig *iconf, const char *entry_str)
static int ConfigSetMempoolSize(
DPDKIfaceConfig *iconf, const char *entry_str, const struct rte_eth_dev_info *dev_info)
{
SCEnter();
if (entry_str == NULL || entry_str[0] == '\0' || strcmp(entry_str, "auto") == 0) {
@ -563,8 +571,7 @@ static int ConfigSetMempoolSize(DPDKIfaceConfig *iconf, const char *entry_str)
SCReturnInt(-EINVAL);
}
iconf->mempool_size = MempoolSizeCalculate(
iconf->nb_rx_queues, iconf->nb_rx_desc, iconf->nb_tx_queues, iconf->nb_tx_desc);
iconf->mempool_size = MempoolSizeCalculate(iconf, dev_info);
SCReturnInt(0);
}
@ -574,15 +581,13 @@ static int ConfigSetMempoolSize(DPDKIfaceConfig *iconf, const char *entry_str)
SCReturnInt(-EINVAL);
}
if (MempoolSizeCalculate(
iconf->nb_rx_queues, iconf->nb_rx_desc, iconf->nb_tx_queues, iconf->nb_tx_desc) >
uint32_t required_mp_size = MempoolSizeCalculate(iconf, dev_info);
if (required_mp_size >
iconf->mempool_size + 1) { // +1 to mask mempool size advice given in Suricata 7.0.x -
// mp_size should be n = (2^q - 1)
SCLogError("%s: mempool size is likely too small for the number of descriptors and queues, "
"set to \"auto\" or adjust to the value of \"%" PRIu32 "\"",
iconf->iface,
MempoolSizeCalculate(iconf->nb_rx_queues, iconf->nb_rx_desc, iconf->nb_tx_queues,
iconf->nb_tx_desc));
iconf->iface, required_mp_size);
SCReturnInt(-ERANGE);
}
@ -950,8 +955,8 @@ static int ConfigLoad(DPDKIfaceConfig *iconf, const char *iface)
retval = SCConfGetChildValueWithDefault(
if_root, if_default, dpdk_yaml.mempool_size, &entry_str) != 1
? ConfigSetMempoolSize(iconf, DPDK_CONFIG_DEFAULT_MEMPOOL_SIZE)
: ConfigSetMempoolSize(iconf, entry_str);
? ConfigSetMempoolSize(iconf, DPDK_CONFIG_DEFAULT_MEMPOOL_SIZE, &dev_info)
: ConfigSetMempoolSize(iconf, entry_str, &dev_info);
if (retval < 0)
SCReturnInt(retval);

@ -73,7 +73,7 @@ typedef struct DPDKIfaceConfig_ {
uint16_t nb_tx_desc;
uint32_t mempool_size;
uint32_t mempool_cache_size;
bool mempool_cache_size_auto;
bool mempool_cache_size_auto; // auto cache size based on mempool size
DPDKDeviceResources *pkt_mempools;
uint16_t linkup_timeout; // in seconds how long to wait for link to come up
SC_ATOMIC_DECLARE(uint16_t, ref);

@ -81,6 +81,79 @@ uint16_t BondingMemberDevicesGet(
#endif
}
/**
* \brief Callback for rte_kvargs_process that increments a counter.
*/
static int BondingMemberCountCb(
const char *key __rte_unused, const char *value __rte_unused, void *opaque)
{
uint16_t *cnt = opaque;
(*cnt)++;
return 0;
}
/**
* \brief Count bonding member devices from the device's devargs.
*
* Bonding members are only attached when rte_eth_dev_configure() is called
* (inside bond_ethdev_configure), so rte_eth_bond_members_get() returns 0
* during early config. Instead, parse the devargs stored during device probe
* to count member/slave entries.
*
* \param dev_info device info (must be non-NULL)
* \return number of member devices found, 0 on any failure
*/
static uint16_t BondingMemberDevCountFromDevargs(const struct rte_eth_dev_info *dev_info)
{
if (dev_info->device == NULL) {
return 0;
}
#if RTE_VERSION >= RTE_VERSION_NUM(22, 11, 0, 0)
const struct rte_devargs *devargs = rte_dev_devargs(dev_info->device);
#else
const struct rte_devargs *devargs = dev_info->device->devargs;
#endif
if (devargs == NULL || devargs->args == NULL) {
return 0;
}
struct rte_kvargs *kvargs = rte_kvargs_parse(devargs->args, NULL);
if (kvargs == NULL) {
return 0;
}
uint16_t count = 0;
int ret;
#if RTE_VERSION >= RTE_VERSION_NUM(23, 11, 0, 0)
ret = rte_kvargs_process(kvargs, "member", BondingMemberCountCb, &count);
#else
ret = rte_kvargs_process(kvargs, "slave", BondingMemberCountCb, &count);
#endif
rte_kvargs_free(kvargs);
return ret == 0 ? count : 0;
}
uint32_t BondingMempoolSizeCalculate(
uint16_t bond_pid, const struct rte_eth_dev_info *dev_info, uint32_t curr_mempool_size)
{
if (curr_mempool_size == 0) {
return 0;
}
uint16_t cnt = BondingMemberDevCountFromDevargs(dev_info);
if (cnt == 0) {
// don't adjust if unable to determine the number of bonded devices
return curr_mempool_size;
} else if (curr_mempool_size > UINT32_MAX / cnt) {
FatalError("%s: mempool size too large to adjust for %u bonded devices",
DPDKGetPortNameByPortID(bond_pid), cnt);
}
return curr_mempool_size * cnt;
}
int32_t BondingAllDevicesSameDriver(uint16_t bond_pid)
{
uint16_t bonded_devs[RTE_MAX_ETHPORTS] = { 0 };

@ -25,12 +25,15 @@
#define UTIL_DPDK_BONDING_H
#include "suricata-common.h"
#include "util-dpdk-common.h"
#ifdef HAVE_DPDK
int32_t BondingIsBond(uint16_t pid);
uint16_t BondingMemberDevicesGet(
uint16_t bond_pid, uint16_t bonded_devs[], uint16_t bonded_devs_length);
uint32_t BondingMempoolSizeCalculate(
uint16_t bond_pid, const struct rte_eth_dev_info *dev_info, uint32_t mempool_size);
int32_t BondingAllDevicesSameDriver(uint16_t bond_pid);
const char *BondingDeviceDriverGet(uint16_t bond_pid);

@ -37,6 +37,7 @@
#include <rte_mempool.h>
#include <rte_mbuf.h>
#include <rte_flow.h>
#include <rte_kvargs.h>
#include <rte_version.h>
#if RTE_VERSION < RTE_VERSION_NUM(22, 0, 0, 0)

Loading…
Cancel
Save