* [PATCH v1 4/4] app/testpmd: add TPH stash objects configuration
From: Chengwen Feng @ 2026-05-08 9:28 UTC (permalink / raw)
To: thomas, stephen; +Cc: dev, wathsala.vithanage
In-Reply-To: <20260508092855.51987-1-fengchengwen@huawei.com>
Add --tph-stash-objects command line option to configure PCIe TPH cache
stash objects for Rx queues. Implement enable/disable logic during
packet forwarding start/stop with device capability checks.
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
---
app/test-pmd/parameters.c | 20 ++++++++++
app/test-pmd/testpmd.c | 81 +++++++++++++++++++++++++++++++++++++++
app/test-pmd/testpmd.h | 1 +
3 files changed, 102 insertions(+)
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index ecbd618f00..ae31d9ba4c 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -79,6 +79,8 @@ enum {
TESTPMD_OPT_NO_NUMA_NUM,
#define TESTPMD_OPT_MP_ANON "mp-anon"
TESTPMD_OPT_MP_ANON_NUM,
+#define TESTPMD_OPT_TPH_STASH_OBJECTS "tph-stash-objects"
+ TESTPMD_OPT_TPH_STASH_OBJECTS_NUM,
#define TESTPMD_OPT_PORT_NUMA_CONFIG "port-numa-config"
TESTPMD_OPT_PORT_NUMA_CONFIG_NUM,
#define TESTPMD_OPT_RING_NUMA_CONFIG "ring-numa-config"
@@ -289,6 +291,7 @@ static const struct option long_options[] = {
NO_ARG(TESTPMD_OPT_NUMA),
NO_ARG(TESTPMD_OPT_NO_NUMA),
NO_ARG(TESTPMD_OPT_MP_ANON), /* deprecated */
+ REQUIRED_ARG(TESTPMD_OPT_TPH_STASH_OBJECTS),
REQUIRED_ARG(TESTPMD_OPT_PORT_NUMA_CONFIG),
REQUIRED_ARG(TESTPMD_OPT_RING_NUMA_CONFIG),
REQUIRED_ARG(TESTPMD_OPT_SOCKET_NUM),
@@ -1140,6 +1143,23 @@ launch_args_parse(int argc, char** argv)
"native, anon, xmem or xmemhuge\n",
optarg);
break;
+ case TESTPMD_OPT_TPH_STASH_OBJECTS_NUM:
+ if (!strcmp(optarg, "rxdesc"))
+ tph_stash_objects = RTE_ETH_CACHE_STASH_OBJ_RX_DESC;
+ else if (!strcmp(optarg, "rxheader"))
+ tph_stash_objects = RTE_ETH_CACHE_STASH_OBJ_RX_HEADER;
+ else if (!strcmp(optarg, "rxpayload"))
+ tph_stash_objects = RTE_ETH_CACHE_STASH_OBJ_RX_PAYLOAD;
+ else if (!strcmp(optarg, "rxdata"))
+ tph_stash_objects = RTE_ETH_CACHE_STASH_OBJ_RX_HEADER |
+ RTE_ETH_CACHE_STASH_OBJ_RX_PAYLOAD;
+ else if (!strcmp(optarg, "rxall"))
+ tph_stash_objects = RTE_ETH_CACHE_STASH_OBJ_RX_DESC |
+ RTE_ETH_CACHE_STASH_OBJ_RX_HEADER |
+ RTE_ETH_CACHE_STASH_OBJ_RX_PAYLOAD;
+ else
+ rte_exit(EXIT_FAILURE, "unknown tph stash mode %s\n", optarg);
+ break;
case TESTPMD_OPT_PORT_NUMA_CONFIG_NUM:
if (parse_portnuma_config(optarg))
rte_exit(EXIT_FAILURE,
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index e2569d9e30..10d9218a9c 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -136,6 +136,11 @@ uint8_t socket_num = UMA_NO_CONFIG;
*/
uint8_t mp_alloc_type = MP_ALLOC_NATIVE;
+/*
+ * PCIE TPH stash objects.
+ */
+uint64_t tph_stash_objects;
+
/*
* Store specified sockets on which memory pool to be used by ports
* is allocated.
@@ -2540,6 +2545,77 @@ update_queue_state(portid_t pid)
}
}
+static void
+start_tph_stash(void)
+{
+ struct rte_eth_cache_stash_capability capa;
+ struct rte_eth_cache_stash_config config;
+ struct fwd_config *cfg = &cur_fwd_config;
+ struct fwd_stream *fs;
+ lcoreid_t lc_id;
+ streamid_t sm_id;
+ portid_t pt_id;
+ int ret;
+ int i;
+
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ ret = rte_eth_cache_stash_get(pt_id, &capa);
+ if (ret != 0 || (capa.supported_types & RTE_ETH_CACHE_STASH_TYPE_TPH) == 0) {
+ fprintf(stderr, "%s: (port %u) don't support tph stash!\n",
+ __func__, pt_id);
+ return;
+ }
+ if ((capa.supported_objects & tph_stash_objects) != tph_stash_objects) {
+ fprintf(stderr, "%s: (port %u) don't support objects=0x%lx 0x%lx\n",
+ __func__, pt_id, tph_stash_objects, capa.supported_objects);
+ return;
+ }
+ memset(&config, 0, sizeof(config));
+ config.dev.type = RTE_ETH_CACHE_STASH_TYPE_TPH;
+ ret = rte_eth_cache_stash_set(pt_id, RTE_ETH_CACHE_STASH_OP_DEV_ENABLE, &config);
+ if (ret != 0) {
+ fprintf(stderr, "%s: (port %u) enable tph failed! ret=%d\n",
+ __func__, pt_id, ret);
+ return;
+ }
+ }
+
+ for (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) {
+ for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) {
+ fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
+ memset(&config, 0, sizeof(config));
+ config.queue.lcore_id = fwd_lcores_cpuids[lc_id];
+ config.queue.queue_id = fs->rx_queue;
+ config.queue.objects = tph_stash_objects;
+ ret = rte_eth_cache_stash_set(fs->rx_port,
+ RTE_ETH_CACHE_STASH_OP_QUEUE_ENABLE, &config);
+ if (ret != 0)
+ fprintf(stderr, "%s: (port %u) enable rx-queue=%u cpu=%u stash ret=%d\n",
+ __func__, fs->rx_port, fs->rx_queue,
+ fwd_lcores_cpuids[lc_id], ret);
+ }
+ }
+}
+
+static void
+stop_tph_stash(void)
+{
+ struct rte_eth_cache_stash_config config;
+ portid_t pt_id;
+ int ret;
+ int i;
+
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ memset(&config, 0, sizeof(config));
+ ret = rte_eth_cache_stash_set(pt_id, RTE_ETH_CACHE_STASH_OP_DEV_DISABLE, &config);
+ if (ret != 0)
+ fprintf(stderr, "%s: (port %u) disable tph stash ret=%d\n",
+ __func__, pt_id, ret);
+ }
+}
+
/*
* Launch packet forwarding configuration.
*/
@@ -2614,6 +2690,9 @@ start_packet_forwarding(int with_tx_first)
if(!no_flush_rx)
flush_fwd_rx_queues();
+ if (tph_stash_objects > 0)
+ start_tph_stash();
+
rxtx_config_display();
fwd_stats_reset();
@@ -2649,6 +2728,8 @@ stop_packet_forwarding(void)
fwd_lcores[lc_id]->stopped = 1;
printf("\nWaiting for lcores to finish...\n");
rte_eal_mp_wait_lcore();
+ if (tph_stash_objects > 0)
+ stop_tph_stash();
port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end;
if (port_fwd_end != NULL) {
for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 9b60ebd7fc..4124d40fda 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -535,6 +535,7 @@ extern uint8_t flow_isolate_all; /**< set by "--flow-isolate-all */
extern uint8_t no_flow_flush; /**< set by "--disable-flow-flush" parameter */
extern uint8_t mp_alloc_type;
/**< set by "--mp-anon" or "--mp-alloc" parameter */
+extern uint64_t tph_stash_objects; /**< set by "--tph-stash-objects" parameter */
extern uint32_t eth_link_speed;
extern uint8_t no_link_check; /**<set by "--disable-link-check" parameter */
extern uint8_t no_device_start; /**<set by "--disable-device-start" parameter */
--
2.17.1
^ permalink raw reply related
* [PATCH v1 3/4] net/e1000: add cache stash support via TPH
From: Chengwen Feng @ 2026-05-08 9:28 UTC (permalink / raw)
To: thomas, stephen; +Cc: dev, wathsala.vithanage
In-Reply-To: <20260508092855.51987-1-fengchengwen@huawei.com>
Implement ethdev generic cache stash operations for igb PMD
using PCIe TPH (Transaction Processing Hints) as the underlying
mechanism.
The implementation supports:
- Query TPH based stash capabilities
- Device-level global enable/disable of TPH
- Per-queue TPH stashing configuration with target lcore
- Configure stashing objects (Rx descriptor, payload, etc.)
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
---
drivers/net/intel/e1000/base/e1000_hw.h | 2 +
drivers/net/intel/e1000/base/e1000_vf.h | 2 +
drivers/net/intel/e1000/igb_ethdev.c | 221 ++++++++++++++++++++++++
3 files changed, 225 insertions(+)
diff --git a/drivers/net/intel/e1000/base/e1000_hw.h b/drivers/net/intel/e1000/base/e1000_hw.h
index 9b1fafd75c..3e8e21b194 100644
--- a/drivers/net/intel/e1000/base/e1000_hw.h
+++ b/drivers/net/intel/e1000/base/e1000_hw.h
@@ -1092,6 +1092,8 @@ struct e1000_hw {
u16 vendor_id;
u8 revision_id;
+
+ u8 tph_mode;
};
#include "e1000_82541.h"
diff --git a/drivers/net/intel/e1000/base/e1000_vf.h b/drivers/net/intel/e1000/base/e1000_vf.h
index 4bec21c935..dd3cef254e 100644
--- a/drivers/net/intel/e1000/base/e1000_vf.h
+++ b/drivers/net/intel/e1000/base/e1000_vf.h
@@ -248,6 +248,8 @@ struct e1000_hw {
u16 vendor_id;
u8 revision_id;
+
+ u8 tph_mode;
};
enum e1000_promisc_type {
diff --git a/drivers/net/intel/e1000/igb_ethdev.c b/drivers/net/intel/e1000/igb_ethdev.c
index ef1599ac38..7aea37d017 100644
--- a/drivers/net/intel/e1000/igb_ethdev.c
+++ b/drivers/net/intel/e1000/igb_ethdev.c
@@ -241,6 +241,10 @@ static int igb_tx_burst_mode_get(struct rte_eth_dev *dev,
__rte_unused uint16_t queue_id, struct rte_eth_burst_mode *mode);
static int igb_rx_burst_mode_get(struct rte_eth_dev *dev,
__rte_unused uint16_t queue_id, struct rte_eth_burst_mode *mode);
+static int eth_igb_cache_stash_get(struct rte_eth_dev *dev,
+ struct rte_eth_cache_stash_capability *capa);
+static int eth_igb_cache_stash_set(struct rte_eth_dev *dev, enum rte_eth_cache_stash_op op,
+ struct rte_eth_cache_stash_config *config);
/*
* Define VF Stats MACRO for Non "cleared on read" register
@@ -402,6 +406,8 @@ static const struct eth_dev_ops eth_igb_ops = {
.timesync_read_time = igb_timesync_read_time,
.timesync_write_time = igb_timesync_write_time,
.read_clock = eth_igb_read_clock,
+ .cache_stash_get = eth_igb_cache_stash_get,
+ .cache_stash_set = eth_igb_cache_stash_set,
};
/*
@@ -5692,6 +5698,221 @@ igb_filter_restore(struct rte_eth_dev *dev)
return 0;
}
+static int
+eth_igb_cache_stash_get(struct rte_eth_dev *dev, struct rte_eth_cache_stash_capability *capa)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ uint32_t support_modes, st_table_sz;
+ int ret;
+
+ ret = rte_pci_tph_query(pci_dev, &support_modes, &st_table_sz);
+ if (ret != 0)
+ return -ENOTSUP;
+ capa->supported_types = RTE_ETH_CACHE_STASH_TYPE_TPH;
+ capa->supported_objects = RTE_ETH_CACHE_STASH_OBJ_RX_DESC |
+ RTE_ETH_CACHE_STASH_OBJ_RX_HEADER |
+ RTE_ETH_CACHE_STASH_OBJ_RX_PAYLOAD |
+ RTE_ETH_CACHE_STASH_OBJ_TX_DESC |
+ RTE_ETH_CACHE_STASH_OBJ_TX_HEADER |
+ RTE_ETH_CACHE_STASH_OBJ_TX_PAYLOAD;
+ return 0;
+}
+
+static int
+eth_igb_cache_stash_dev_enable(struct rte_eth_dev *dev,
+ struct rte_eth_cache_stash_config *config)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ uint32_t support_modes, st_table_sz;
+ uint32_t mode;
+ int ret;
+
+ if (hw->tph_mode != 0) {
+ PMD_DRV_LOG(ERR, "Already enable tph_mode=%u", hw->tph_mode);
+ return -EINVAL;
+ }
+
+ if (config->dev.type != RTE_ETH_CACHE_STASH_TYPE_TPH) {
+ PMD_DRV_LOG(ERR, "Unsupported stash type=%u!", config->dev.type);
+ return -ENOTSUP;
+ }
+
+ ret = rte_pci_tph_query(pci_dev, &support_modes, &st_table_sz);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Query TPH failed! ret=%d", ret);
+ return -ENOTSUP;
+ }
+
+ if (support_modes & RTE_PCI_TPH_MODE_IV)
+ mode = RTE_PCI_TPH_MODE_IV;
+ else if (support_modes & RTE_PCI_TPH_MODE_DS)
+ mode = RTE_PCI_TPH_MODE_DS;
+ else
+ return -ENOTSUP;
+ ret = rte_pci_tph_enable(pci_dev, mode);
+ if (ret == 0)
+ hw->tph_mode = mode;
+
+ return ret;
+}
+
+static void
+eth_igb_cache_stash_dev_clear(struct rte_eth_dev *dev)
+{
+ uint32_t nb_queues = RTE_MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues);
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ struct rte_pci_tph_entry ent = {0};
+ uint32_t reg;
+ uint32_t i;
+
+ for (i = 0; i < nb_queues; i++) {
+ ent.cpu = UINT32_MAX;
+ ent.index = i;
+ rte_pci_tph_st_set(pci_dev, &ent, 1);
+ reg = E1000_READ_REG(hw, E1000_RXCTL(i));
+ reg &= ~RTE_BIT32(0);
+ reg &= ~RTE_BIT32(1);
+ reg &= ~RTE_BIT32(2);
+ reg &= ~RTE_BIT32(3);
+ reg &= ~RTE_SHIFT_VAL32(0xFF, 24);
+ E1000_WRITE_REG(hw, E1000_RXCTL(i), reg);
+ }
+}
+
+static int
+eth_igb_cache_stash_dev_disable(struct rte_eth_dev *dev)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ int ret;
+
+ if (hw->tph_mode == 0) {
+ PMD_DRV_LOG(ERR, "Already disable TPH!");
+ return -EINVAL;
+ }
+
+ eth_igb_cache_stash_dev_clear(dev);
+ ret = rte_pci_tph_disable(pci_dev);
+ if (ret == 0)
+ hw->tph_mode = 0;
+
+ return ret;
+}
+
+static int
+eth_igb_cache_stash_queue_enable(struct rte_eth_dev *dev,
+ struct rte_eth_cache_stash_config *config)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ uint32_t queue_id = config->queue.queue_id;
+ struct rte_pci_tph_entry ent = {0};
+ uint32_t reg;
+ uint16_t st;
+ int ret;
+
+ if (hw->tph_mode == 0) {
+ PMD_DRV_LOG(ERR, "Device TPH was not enabled!");
+ return -EINVAL;
+ }
+
+ if (queue_id > RTE_MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues)) {
+ PMD_DRV_LOG(ERR, "Invalid queue_id when enable stash!");
+ return -EINVAL;
+ }
+
+ ent.cpu = config->queue.lcore_id;
+ ent.index = queue_id;
+ ret = rte_pci_tph_st_get(pci_dev, &ent, 1);
+ if (ret != 0) {
+ PMD_DRV_LOG(ERR, "Failed to get device queue=%u st of cpu=%u ret=%u",
+ queue_id, config->queue.lcore_id, ret);
+ return ret;
+ }
+ st = ent.st;
+
+ reg = E1000_READ_REG(hw, E1000_RXCTL(queue_id));
+ PMD_DRV_LOG(DEBUG, "[Enable] Queue=%u rxctl register init val=0x%x", queue_id, reg);
+ if (config->queue.objects & RTE_ETH_CACHE_STASH_OBJ_RX_DESC) {
+ reg |= RTE_BIT32(0);
+ reg |= RTE_BIT32(1);
+ } else {
+ reg &= ~RTE_BIT32(0);
+ reg &= ~RTE_BIT32(1);
+ }
+ if (config->queue.objects & RTE_ETH_CACHE_STASH_OBJ_RX_HEADER)
+ reg |= RTE_BIT32(2);
+ else
+ reg &= ~RTE_BIT32(2);
+ if (config->queue.objects & RTE_ETH_CACHE_STASH_OBJ_RX_PAYLOAD)
+ reg |= RTE_BIT32(3);
+ else
+ reg &= ~RTE_BIT32(3);
+ /* I350 must encoding st in high 8bit, and ST in config-space is no needed! */
+ reg |= RTE_SHIFT_VAL32(st, 24);
+ E1000_WRITE_REG(hw, E1000_RXCTL(queue_id), reg);
+ PMD_DRV_LOG(DEBUG, "[Enable] Queue=%u rxctl register after val=0x%x", queue_id, reg);
+
+ PMD_DRV_LOG(DEBUG, "[Enable] Enable device queue=%u st of cpu=%u success!",
+ queue_id, config->queue.lcore_id);
+
+ return 0;
+}
+
+static int
+eth_igb_cache_stash_queue_disable(struct rte_eth_dev *dev,
+ struct rte_eth_cache_stash_config *config)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ uint32_t queue_id = config->queue.queue_id;
+ uint32_t reg;
+
+ if (hw->tph_mode == 0) {
+ PMD_DRV_LOG(ERR, "Device TPH was not enabled!");
+ return -EINVAL;
+ }
+
+ if (queue_id > RTE_MAX(dev->data->nb_rx_queues, dev->data->nb_tx_queues)) {
+ PMD_DRV_LOG(ERR, "Invalid queue_id when enable stash!");
+ return -EINVAL;
+ }
+
+ reg = E1000_READ_REG(hw, E1000_RXCTL(queue_id));
+ PMD_DRV_LOG(DEBUG, "[Disable] Queue=%u rxctl register init val=0x%x", queue_id, reg);
+ reg &= ~RTE_BIT32(0);
+ reg &= ~RTE_BIT32(1);
+ reg &= ~RTE_BIT32(2);
+ reg &= ~RTE_BIT32(3);
+ reg &= ~RTE_SHIFT_VAL32(0xFF, 24);
+ E1000_WRITE_REG(hw, E1000_RXCTL(queue_id), reg);
+ PMD_DRV_LOG(DEBUG, "[Disable] Queue=%u rxctl register after val=0x%x", queue_id, reg);
+
+ PMD_DRV_LOG(DEBUG, "[Disable] disable device queue=%u st of cpu=%u success!",
+ queue_id, config->queue.lcore_id);
+
+ return 0;
+}
+
+static int
+eth_igb_cache_stash_set(struct rte_eth_dev *dev, enum rte_eth_cache_stash_op op,
+ struct rte_eth_cache_stash_config *config)
+{
+ switch (op) {
+ case RTE_ETH_CACHE_STASH_OP_DEV_ENABLE:
+ return eth_igb_cache_stash_dev_enable(dev, config);
+ case RTE_ETH_CACHE_STASH_OP_DEV_DISABLE:
+ return eth_igb_cache_stash_dev_disable(dev);
+ case RTE_ETH_CACHE_STASH_OP_QUEUE_ENABLE:
+ return eth_igb_cache_stash_queue_enable(dev, config);
+ case RTE_ETH_CACHE_STASH_OP_QUEUE_DISABLE:
+ return eth_igb_cache_stash_queue_disable(dev, config);
+ default:
+ return -ENOTSUP;
+ }
+}
+
RTE_PMD_REGISTER_PCI(net_e1000_igb, rte_igb_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_e1000_igb, pci_id_igb_map);
RTE_PMD_REGISTER_KMOD_DEP(net_e1000_igb, "* igb_uio | uio_pci_generic | vfio-pci");
--
2.17.1
^ permalink raw reply related
* [PATCH v10] eal/x86: optimize memcpy of small sizes
From: Morten Brørup @ 2026-05-08 9:58 UTC (permalink / raw)
To: dev, Bruce Richardson, Konstantin Ananyev, Vipin Varghese,
Stephen Hemminger, Liangxing Wang
Cc: Thiyagarajan P, Bala Murali Krishna, Anatoly Burakov,
Vladimir Medvedkin, Morten Brørup, Konstantin Ananyev
In-Reply-To: <20251120114554.950287-1-mb@smartsharesystems.com>
The implementation for copying up to 64 bytes does not depend on address
alignment with the size of the CPU's vector registers. Nonetheless, the
exact same code for copying up to 64 bytes was present in both the aligned
copy function and all the CPU vector register size specific variants of
the unaligned copy functions.
With this patch, the implementation for copying up to 64 bytes was
consolidated into one instance, located in the common copy function,
before checking alignment requirements.
This provides three benefits:
1. No copy-paste in the source code.
2. A performance gain for copying up to 64 bytes, because the
address alignment check is avoided in this case.
3. Reduced instruction memory footprint, because the compiler only
generates one instance of the function for copying up to 64 bytes, instead
of two instances (one in the unaligned copy function, and one in the
aligned copy function).
Furthermore, __rte_restrict was added to source and destination addresses.
And finally, the missing implementation of rte_mov48() was added.
Regarding performance...
The memcpy performance test (cache-to-cache copy) shows:
Copying up to 15 bytes takes ca. 4.5 cycles, versus ca. 6.5 cycles before.
Copying 8 bytes takes 4 cycles, versus 7 cycles before.
Copying 16 bytes takes 2 cycles, versus 4 cycles before.
Copying 64 bytes takes 4 cycles, versus 7 cycles before.
Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>
---
v10:
* Reverted removal of ignoring stringop-overflow warnings.
Instead, added a comment about the reason for ignoring them.
Some drivers still use elems[1] instead of elems[] for structures with
flexible arrays.
IMO, the drivers should be fixed, or the warnings should be igmored
there; but I'm picking the easy solution, and not changing this.
If they were using standard memcpy(), warnings would also be emitted.
v9:
* Removed new functions rte_mov16_to_32() and rte_mov32_to_64(), and moved
their implementations into rte_memcpy() instead.
There is no need for such public functions, and having them separate did
not improve source code readability.
* Kept acks from Bruce and Konstantin (both given to v7).
v8:
* Reverted the first branch from size <= 16 back to size < 16, restored
the original rte_mov15_or_less() function, and removed the new
rte_mov16_or_less() function.
When rte_memcpy() is used for copying an array of pointers, and the
number of pointers to copy is low (size <= 64 bytes), it is more likely
that the number of pointers to copy is 1 than 2.
The rte_mov15_or_less() implementation handles copying 8 bytes more
efficiently than the rte_mov16_or_less() implementation, which copied
the 8-byte pointer twice.
Also note that with rte_mov15_or_less(), the compiler can optimize away
the branches handling n & 1, n & 2 and n & 4 when it is known at compile
time that (8-byte) pointers are being copied. (For 32-bit architecture,
the n & 4 will not be optimized away when copying pointers.)
This reversion also makes the patch less revolutionary and more
incremental.
* Removed a lot of code for handling compile time known sizes. (Bruce)
The rte_memcpy() function should not be used for small copies with
compile time known sizes, so handling it is considered superfluous.
Removing it improves source code readability. And reduces the size of
the patch.
* Kept acks from Bruce and Konstantin (both given to v7).
v7:
* Updated patch description. Mainly to clarify that the changes related to
copying up to 64 bytes simply replaces multiple instances of copy-pasted
code with one common instance.
* Fixed copy of compile time known 16 bytes in rte_mov17_to_32(). (Vipin)
* Rebased.
v6:
* Went back to using rte_uintN_alias structures for copying instead of
using memcpy(). They were there for a reason.
(Inspired by the discussion about optimizing the checksum function.)
* Removed note about copying uninitialized data.
* Added __rte_restrict to source and destination addresses.
Updated function descriptions from "should" to "must" not overlap.
* Changed rte_mov48() AVX implementation to copy 32+16 bytes instead of
copying 32 + 32 overlapping bytes. (Konstantin)
* Ignoring "-Wstringop-overflow" is not needed, so it was removed.
v5:
* Reverted v4: Replace SSE2 _mm_loadu_si128() with SSE3 _mm_lddqu_si128().
It was slower.
* Improved some comments. (Konstantin Ananyev)
* Moved the size range 17..32 inside the size <= 64 branch, so when
building for SSE, the generated code can start copying the first
16 bytes before comparing if the size is greater than 32 or not.
* Just require RTE_MEMCPY_AVX for using rte_mov32() in rte_mov33_to_64().
v4:
* Replace SSE2 _mm_loadu_si128() with SSE3 _mm_lddqu_si128().
v3:
* Fixed typo in comment.
v2:
* Updated patch title to reflect that the performance is improved.
* Use the design pattern of two overlapping stores for small copies too.
* Expanded first branch from size < 16 to size <= 16.
* Handle more compile time constant copy sizes.
---
lib/eal/x86/include/rte_memcpy.h | 242 +++++++++++++------------------
1 file changed, 103 insertions(+), 139 deletions(-)
diff --git a/lib/eal/x86/include/rte_memcpy.h b/lib/eal/x86/include/rte_memcpy.h
index 46d34b8081..d6dfac19aa 100644
--- a/lib/eal/x86/include/rte_memcpy.h
+++ b/lib/eal/x86/include/rte_memcpy.h
@@ -22,6 +22,7 @@
extern "C" {
#endif
+/* Workaround for drivers using elems[1] instead of elems[] for flexible arrays. */
#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION >= 100000)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
@@ -40,9 +41,6 @@ extern "C" {
/**
* Copy bytes from one location to another. The locations must not overlap.
*
- * @note This is implemented as a macro, so it's address should not be taken
- * and care is needed as parameter expressions may be evaluated multiple times.
- *
* @param dst
* Pointer to the destination of the data.
* @param src
@@ -53,15 +51,15 @@ extern "C" {
* Pointer to the destination data.
*/
static __rte_always_inline void *
-rte_memcpy(void *dst, const void *src, size_t n);
+rte_memcpy(void *__rte_restrict dst, const void *__rte_restrict src, size_t n);
/**
* Copy bytes from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
* Use with n <= 15.
*/
static __rte_always_inline void *
-rte_mov15_or_less(void *dst, const void *src, size_t n)
+rte_mov15_or_less(void *__rte_restrict dst, const void *__rte_restrict src, size_t n)
{
/**
* Use the following structs to avoid violating C standard
@@ -103,10 +101,10 @@ rte_mov15_or_less(void *dst, const void *src, size_t n)
/**
* Copy 16 bytes from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
*/
static __rte_always_inline void
-rte_mov16(uint8_t *dst, const uint8_t *src)
+rte_mov16(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src)
{
__m128i xmm0;
@@ -116,10 +114,10 @@ rte_mov16(uint8_t *dst, const uint8_t *src)
/**
* Copy 32 bytes from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
*/
static __rte_always_inline void
-rte_mov32(uint8_t *dst, const uint8_t *src)
+rte_mov32(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src)
{
#if defined RTE_MEMCPY_AVX
__m256i ymm0;
@@ -132,12 +130,29 @@ rte_mov32(uint8_t *dst, const uint8_t *src)
#endif
}
+/**
+ * Copy 48 bytes from one location to another,
+ * locations must not overlap.
+ */
+static __rte_always_inline void
+rte_mov48(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src)
+{
+#if defined RTE_MEMCPY_AVX
+ rte_mov32((uint8_t *)dst, (const uint8_t *)src);
+ rte_mov16((uint8_t *)dst + 32, (const uint8_t *)src + 32);
+#else /* SSE implementation */
+ rte_mov16((uint8_t *)dst + 0 * 16, (const uint8_t *)src + 0 * 16);
+ rte_mov16((uint8_t *)dst + 1 * 16, (const uint8_t *)src + 1 * 16);
+ rte_mov16((uint8_t *)dst + 2 * 16, (const uint8_t *)src + 2 * 16);
+#endif
+}
+
/**
* Copy 64 bytes from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
*/
static __rte_always_inline void
-rte_mov64(uint8_t *dst, const uint8_t *src)
+rte_mov64(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src)
{
#if defined __AVX512F__ && defined RTE_MEMCPY_AVX512
__m512i zmm0;
@@ -152,10 +167,10 @@ rte_mov64(uint8_t *dst, const uint8_t *src)
/**
* Copy 128 bytes from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
*/
static __rte_always_inline void
-rte_mov128(uint8_t *dst, const uint8_t *src)
+rte_mov128(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src)
{
rte_mov64(dst + 0 * 64, src + 0 * 64);
rte_mov64(dst + 1 * 64, src + 1 * 64);
@@ -163,10 +178,10 @@ rte_mov128(uint8_t *dst, const uint8_t *src)
/**
* Copy 256 bytes from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
*/
static __rte_always_inline void
-rte_mov256(uint8_t *dst, const uint8_t *src)
+rte_mov256(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src)
{
rte_mov128(dst + 0 * 128, src + 0 * 128);
rte_mov128(dst + 1 * 128, src + 1 * 128);
@@ -182,10 +197,10 @@ rte_mov256(uint8_t *dst, const uint8_t *src)
/**
* Copy 128-byte blocks from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
*/
static __rte_always_inline void
-rte_mov128blocks(uint8_t *dst, const uint8_t *src, size_t n)
+rte_mov128blocks(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src, size_t n)
{
__m512i zmm0, zmm1;
@@ -202,10 +217,10 @@ rte_mov128blocks(uint8_t *dst, const uint8_t *src, size_t n)
/**
* Copy 512-byte blocks from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
*/
static inline void
-rte_mov512blocks(uint8_t *dst, const uint8_t *src, size_t n)
+rte_mov512blocks(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src, size_t n)
{
__m512i zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7;
@@ -232,45 +247,22 @@ rte_mov512blocks(uint8_t *dst, const uint8_t *src, size_t n)
}
}
+/**
+ * Copy bytes from one location to another,
+ * locations must not overlap.
+ * Use with n > 64.
+ */
static __rte_always_inline void *
-rte_memcpy_generic(void *dst, const void *src, size_t n)
+rte_memcpy_generic_more_than_64(void *__rte_restrict dst, const void *__rte_restrict src,
+ size_t n)
{
void *ret = dst;
size_t dstofss;
size_t bits;
- /**
- * Copy less than 16 bytes
- */
- if (n < 16) {
- return rte_mov15_or_less(dst, src, n);
- }
-
/**
* Fast way when copy size doesn't exceed 512 bytes
*/
- if (__rte_constant(n) && n == 32) {
- rte_mov32((uint8_t *)dst, (const uint8_t *)src);
- return ret;
- }
- if (n <= 32) {
- rte_mov16((uint8_t *)dst, (const uint8_t *)src);
- if (__rte_constant(n) && n == 16)
- return ret; /* avoid (harmless) duplicate copy */
- rte_mov16((uint8_t *)dst - 16 + n,
- (const uint8_t *)src - 16 + n);
- return ret;
- }
- if (__rte_constant(n) && n == 64) {
- rte_mov64((uint8_t *)dst, (const uint8_t *)src);
- return ret;
- }
- if (n <= 64) {
- rte_mov32((uint8_t *)dst, (const uint8_t *)src);
- rte_mov32((uint8_t *)dst - 32 + n,
- (const uint8_t *)src - 32 + n);
- return ret;
- }
if (n <= 512) {
if (n >= 256) {
n -= 256;
@@ -351,10 +343,10 @@ rte_memcpy_generic(void *dst, const void *src, size_t n)
/**
* Copy 128-byte blocks from one location to another,
- * locations should not overlap.
+ * locations must not overlap.
*/
static __rte_always_inline void
-rte_mov128blocks(uint8_t *dst, const uint8_t *src, size_t n)
+rte_mov128blocks(uint8_t *__rte_restrict dst, const uint8_t *__rte_restrict src, size_t n)
{
__m256i ymm0, ymm1, ymm2, ymm3;
@@ -381,41 +373,22 @@ rte_mov128blocks(uint8_t *dst, const uint8_t *src, size_t n)
}
}
+/**
+ * Copy bytes from one location to another,
+ * locations must not overlap.
+ * Use with n > 64.
+ */
static __rte_always_inline void *
-rte_memcpy_generic(void *dst, const void *src, size_t n)
+rte_memcpy_generic_more_than_64(void *__rte_restrict dst, const void *__rte_restrict src,
+ size_t n)
{
void *ret = dst;
size_t dstofss;
size_t bits;
- /**
- * Copy less than 16 bytes
- */
- if (n < 16) {
- return rte_mov15_or_less(dst, src, n);
- }
-
/**
* Fast way when copy size doesn't exceed 256 bytes
*/
- if (__rte_constant(n) && n == 32) {
- rte_mov32((uint8_t *)dst, (const uint8_t *)src);
- return ret;
- }
- if (n <= 32) {
- rte_mov16((uint8_t *)dst, (const uint8_t *)src);
- if (__rte_constant(n) && n == 16)
- return ret; /* avoid (harmless) duplicate copy */
- rte_mov16((uint8_t *)dst - 16 + n,
- (const uint8_t *)src - 16 + n);
- return ret;
- }
- if (n <= 64) {
- rte_mov32((uint8_t *)dst, (const uint8_t *)src);
- rte_mov32((uint8_t *)dst - 32 + n,
- (const uint8_t *)src - 32 + n);
- return ret;
- }
if (n <= 256) {
if (n >= 128) {
n -= 128;
@@ -482,7 +455,7 @@ rte_memcpy_generic(void *dst, const void *src, size_t n)
/**
* Macro for copying unaligned block from one location to another with constant load offset,
* 47 bytes leftover maximum,
- * locations should not overlap.
+ * locations must not overlap.
* Requirements:
* - Store is aligned
* - Load offset is <offset>, which must be immediate value within [1, 15]
@@ -542,7 +515,7 @@ rte_memcpy_generic(void *dst, const void *src, size_t n)
/**
* Macro for copying unaligned block from one location to another,
* 47 bytes leftover maximum,
- * locations should not overlap.
+ * locations must not overlap.
* Use switch here because the aligning instruction requires immediate value for shift count.
* Requirements:
* - Store is aligned
@@ -573,38 +546,23 @@ rte_memcpy_generic(void *dst, const void *src, size_t n)
} \
}
+/**
+ * Copy bytes from one location to another,
+ * locations must not overlap.
+ * Use with n > 64.
+ */
static __rte_always_inline void *
-rte_memcpy_generic(void *dst, const void *src, size_t n)
+rte_memcpy_generic_more_than_64(void *__rte_restrict dst, const void *__rte_restrict src,
+ size_t n)
{
__m128i xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8;
void *ret = dst;
size_t dstofss;
size_t srcofs;
- /**
- * Copy less than 16 bytes
- */
- if (n < 16) {
- return rte_mov15_or_less(dst, src, n);
- }
-
/**
* Fast way when copy size doesn't exceed 512 bytes
*/
- if (n <= 32) {
- rte_mov16((uint8_t *)dst, (const uint8_t *)src);
- if (__rte_constant(n) && n == 16)
- return ret; /* avoid (harmless) duplicate copy */
- rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n);
- return ret;
- }
- if (n <= 64) {
- rte_mov32((uint8_t *)dst, (const uint8_t *)src);
- if (n > 48)
- rte_mov16((uint8_t *)dst + 32, (const uint8_t *)src + 32);
- rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n);
- return ret;
- }
if (n <= 128) {
goto COPY_BLOCK_128_BACK15;
}
@@ -696,44 +654,17 @@ rte_memcpy_generic(void *dst, const void *src, size_t n)
#endif /* __AVX512F__ */
+/**
+ * Copy bytes from one vector register size aligned location to another,
+ * locations must not overlap.
+ * Use with n > 64.
+ */
static __rte_always_inline void *
-rte_memcpy_aligned(void *dst, const void *src, size_t n)
+rte_memcpy_aligned_more_than_64(void *__rte_restrict dst, const void *__rte_restrict src,
+ size_t n)
{
void *ret = dst;
- /* Copy size < 16 bytes */
- if (n < 16) {
- return rte_mov15_or_less(dst, src, n);
- }
-
- /* Copy 16 <= size <= 32 bytes */
- if (__rte_constant(n) && n == 32) {
- rte_mov32((uint8_t *)dst, (const uint8_t *)src);
- return ret;
- }
- if (n <= 32) {
- rte_mov16((uint8_t *)dst, (const uint8_t *)src);
- if (__rte_constant(n) && n == 16)
- return ret; /* avoid (harmless) duplicate copy */
- rte_mov16((uint8_t *)dst - 16 + n,
- (const uint8_t *)src - 16 + n);
-
- return ret;
- }
-
- /* Copy 32 < size <= 64 bytes */
- if (__rte_constant(n) && n == 64) {
- rte_mov64((uint8_t *)dst, (const uint8_t *)src);
- return ret;
- }
- if (n <= 64) {
- rte_mov32((uint8_t *)dst, (const uint8_t *)src);
- rte_mov32((uint8_t *)dst - 32 + n,
- (const uint8_t *)src - 32 + n);
-
- return ret;
- }
-
/* Copy 64 bytes blocks */
for (; n > 64; n -= 64) {
rte_mov64((uint8_t *)dst, (const uint8_t *)src);
@@ -749,12 +680,45 @@ rte_memcpy_aligned(void *dst, const void *src, size_t n)
}
static __rte_always_inline void *
-rte_memcpy(void *dst, const void *src, size_t n)
+rte_memcpy(void *__rte_restrict dst, const void *__rte_restrict src, size_t n)
{
+ /* Fast way when copy size doesn't exceed 64 bytes. */
+ if (n < 16)
+ return rte_mov15_or_less(dst, src, n);
+ if (n <= 32) {
+ if (__rte_constant(n) && n == 32) {
+ rte_mov32((uint8_t *)dst, (const uint8_t *)src);
+ return dst;
+ }
+ rte_mov16((uint8_t *)dst, (const uint8_t *)src);
+ if (__rte_constant(n) && n == 16)
+ return dst; /* avoid (harmless) duplicate copy */
+ rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n);
+ return dst;
+ }
+ if (n <= 64) {
+ if (__rte_constant(n) && n == 64) {
+ rte_mov64((uint8_t *)dst, (const uint8_t *)src);
+ return dst;
+ }
+#if defined RTE_MEMCPY_AVX
+ rte_mov32((uint8_t *)dst, (const uint8_t *)src);
+ rte_mov32((uint8_t *)dst - 32 + n, (const uint8_t *)src - 32 + n);
+#else /* SSE implementation */
+ rte_mov16((uint8_t *)dst + 0 * 16, (const uint8_t *)src + 0 * 16);
+ rte_mov16((uint8_t *)dst + 1 * 16, (const uint8_t *)src + 1 * 16);
+ if (n > 48)
+ rte_mov16((uint8_t *)dst + 2 * 16, (const uint8_t *)src + 2 * 16);
+ rte_mov16((uint8_t *)dst - 16 + n, (const uint8_t *)src - 16 + n);
+#endif
+ return dst;
+ }
+
+ /* Implementation for size > 64 bytes depends on alignment with vector register size. */
if (!(((uintptr_t)dst | (uintptr_t)src) & ALIGNMENT_MASK))
- return rte_memcpy_aligned(dst, src, n);
+ return rte_memcpy_aligned_more_than_64(dst, src, n);
else
- return rte_memcpy_generic(dst, src, n);
+ return rte_memcpy_generic_more_than_64(dst, src, n);
}
#undef ALIGNMENT_MASK
--
2.43.0
^ permalink raw reply related
* RE: [PATCH v1 1/1] net/iavf: fix large VF IRQ mapping
From: Morten Brørup @ 2026-05-08 10:16 UTC (permalink / raw)
To: Burakov, Anatoly, Vladimir Medvedkin, Bruce Richardson
Cc: dev, David Marchand, stephen
In-Reply-To: <3b9ba191-f086-4264-8382-653c06772e17@intel.com>
> From: Morten Brørup
> Sent: Friday, 8 May 2026 11.16
>
> > From: Burakov, Anatoly [mailto:anatoly.burakov@intel.com]
> > Sent: Thursday, 7 May 2026 10.09
> >
> > On 5/6/2026 5:58 PM, David Marchand wrote:
> > > On Wed, 6 May 2026 at 16:07, Anatoly Burakov
> > <anatoly.burakov@intel.com> wrote:
> > >>
> > >
> > > - all those virtchnl list struct have the same elems[1] issue.
> > > Kernel side did some cleanups some time ago, maybe time for DPDK to
> > do
> > > the same...?
> > >
> >
> > Yes, it is indeed time to do the same, but not as part of this
> > patchset,
> > and not before the base driver code is updated to do the same. There
> is
> > some background work happening on that front already, but there are a
> > lot of dependencies and moving parts, so we can't just change this
> > willy
> > nilly.
>
> Is there a timeline for this fix?
>
> With the performance improved rte_memcpy() patch [1], one of the CI
> compilers complains about buffer overflows when writing beyond these
> undersize arrays [2].
> And I'd like to see the performance improved rte_memcpy() merged in
> 26.07.
With v10 of the rte_memcpy() patch [3], I have reverted the removal of the workaround that ignores stringop-overflow warnings in rte_memcpy(), so the patch doesn't depend on fixing the drivers.
Please take note to remove the workaround from rte_memcpy() when the flex array issue in the drivers - using elems[1] instead of elems[] - has been fixed.
Not ignoring buffer overflows in rte_memcpy() might help reveal bugs elsewhere.
Alternatively, move the workaround from rte_memcpy.h to the driver code requiring the workaround.
>
> [1]:
> https://patchwork.dpdk.org/project/dpdk/patch/20260429103548.220354-1-
> mb@smartsharesystems.com/
> [2]:
> https://github.com/ovsrobot/dpdk/actions/runs/25104438552/job/749682184
> 20
[3]: https://patchwork.dpdk.org/project/dpdk/patch/20260508095827.53587-1-mb@smartsharesystems.com/
>
> -Morten
^ permalink raw reply
* Re: [PATCH v3] net/mlx5: prepend implicit items in sync flow creation path
From: Dariusz Sosnowski @ 2026-05-08 12:40 UTC (permalink / raw)
To: Maxime Peim; +Cc: dev, viacheslavo, bingz, orika, suanmingm, matan
In-Reply-To: <20260427123217.510662-1-maxime.peim@gmail.com>
Hi,
Thank you for making the changes. Please see a comment below.
On Mon, Apr 27, 2026 at 02:32:17PM +0200, Maxime Peim wrote:
> +
> + prepend_items = flow_hw_adjust_pattern(dev, &pattern_template_attr, true, items,
> + &orig_item_nb, &item_flags, &copied_items, error);
Adjusted items should also be stored in resource.suffix.items.
In case metadata split is not needed - when mlx5_flow_nta_split_metadata() returns 0 -
only single flow rule will be created, at line 14392 (after applying your patch).
In this case, items are taken from resource.suffix.items.
resource.suffix.items holds pointer to original pattern, so adjusted
pattern is not taken into account.
This case be reproduced as follows:
# --flow-isolate-all disables default flow rules which can
# obfuscate the issue
dpdk-testpmd -a 08:00.0,dv_flow_en=2,representor=vf0-1 -- --flow-isolate-all -i
testpmd> flow create 0 group 0 priority 0 ingress pattern end actions jump group 1 / end
testpmd> flow create 0 group 1 priority 0 ingress pattern end actions queue index 0 / end
Packets sent from VF0 or VF1 will arrive at PF's queue 0.
Best regards,
Dariusz Sosnowski
^ permalink raw reply
* Re: [PATCH 1/1] net/mlx5: fix crash if malloc FCQS fails
From: Dariusz Sosnowski @ 2026-05-08 12:51 UTC (permalink / raw)
To: Yunjian Wang
Cc: dev, matan, suanmingm, rasland, viacheslavo, jerry.lilijun,
stable
In-Reply-To: <1777027713-91888-1-git-send-email-wangyunjian@huawei.com>
On Fri, Apr 24, 2026 at 06:48:33PM +0800, Yunjian Wang wrote:
> A crash is triggered when memory malloc for FCQS fails. Currently,
> the abnormal branch releases the txq, and it removes the 'txq_ctrl->obj'
> from the linked list, but the 'txq_ctrl->obj' has not actually been
> added to the linked list yet. This triggers a null pointer reference
> issue.
>
> The call stack is as follows:
> Program terminated with signal 11, Segmentation fault.
> 1210 LIST_REMOVE(txq_ctrl->obj, next);
> (gdb) bt
> #0 mlx5_txq_release
> #1 mlx5_txq_start
> #2 mlx5_dev_start
> #3 rte_eth_dev_start
> #4 member_start
> #5 bond_ethdev_start
>
> Fixes: f49f44839df3 ("net/mlx5: share Tx control code")
> Cc: stable@dpdk.org
>
> Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Thank you for the contribution.
Best regards,
Dariusz Sosnowski
^ permalink raw reply
* [PATCH v1 0/2] Update IDPF Base Code
From: Soumyadeep Hore @ 2026-05-09 1:54 UTC (permalink / raw)
To: bruce.richardson, manoj.kumar.subbarao, aman.deep.singh, dev
Update idpf base code with compatible configuration on MEV.
Christopher Pau (1):
net/idpf/base: add MMG device IDs
Soumyadeep Hore (1):
doc: update recommended matching versions for cpfl and idpf
doc/guides/nics/cpfl.rst | 2 ++
doc/guides/nics/idpf.rst | 2 ++
drivers/net/intel/idpf/base/idpf_devids.h | 3 +++
3 files changed, 7 insertions(+)
--
2.47.1
^ permalink raw reply
* [PATCH v1 1/2] net/idpf/base: add MMG device IDs
From: Soumyadeep Hore @ 2026-05-09 1:54 UTC (permalink / raw)
To: bruce.richardson, manoj.kumar.subbarao, aman.deep.singh, dev
Cc: Christopher Pau
In-Reply-To: <20260509015408.29188-1-soumyadeep.hore@intel.com>
From: Christopher Pau <christopher.pau@intel.com>
Add MMG device ids for PF and VF.
Signed-off-by: Christopher Pau <christopher.pau@intel.com>
Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com>
---
drivers/net/intel/idpf/base/idpf_devids.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/intel/idpf/base/idpf_devids.h b/drivers/net/intel/idpf/base/idpf_devids.h
index 1ae99fcee1..8b10ef9e32 100644
--- a/drivers/net/intel/idpf/base/idpf_devids.h
+++ b/drivers/net/intel/idpf/base/idpf_devids.h
@@ -10,7 +10,10 @@
/* Device IDs */
#define IDPF_DEV_ID_PF 0x1452
+#define IDPF_DEV_ID_PF1 0x11DF
+#define IDPF_DEV_ID_CPF1 0x11E0
#define IDPF_DEV_ID_VF 0x145C
+#define IDPF_DEV_ID_VF1 0x0DE2
#define IDPF_DEV_ID_VF_SIOV 0x0DD5
--
2.47.1
^ permalink raw reply related
* [PATCH v1 2/2] doc: update recommended matching versions for cpfl and idpf
From: Soumyadeep Hore @ 2026-05-09 1:54 UTC (permalink / raw)
To: bruce.richardson, manoj.kumar.subbarao, aman.deep.singh, dev
In-Reply-To: <20260509015408.29188-1-soumyadeep.hore@intel.com>
Update the recommended MEV-ts release version corresponding to DPDK
release in the cpfl and idpf drivers documentation.
Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com>
---
doc/guides/nics/cpfl.rst | 2 ++
doc/guides/nics/idpf.rst | 2 ++
2 files changed, 4 insertions(+)
diff --git a/doc/guides/nics/cpfl.rst b/doc/guides/nics/cpfl.rst
index bc42c524ea..da884f5e3b 100644
--- a/doc/guides/nics/cpfl.rst
+++ b/doc/guides/nics/cpfl.rst
@@ -41,6 +41,8 @@ Here is the suggested matching list which has been tested and verified.
+------------+------------------+
| 25.07 | 2.0 |
+------------+------------------+
+ | 26.07 | 2.2 |
+ +------------+------------------+
Configuration
diff --git a/doc/guides/nics/idpf.rst b/doc/guides/nics/idpf.rst
index c7c76190c8..a6f611c09b 100644
--- a/doc/guides/nics/idpf.rst
+++ b/doc/guides/nics/idpf.rst
@@ -37,6 +37,8 @@ Here is the suggested matching list which has been tested and verified.
+------------+---------------+------------------+
| 25.07 | 0.0.772 | 2.0 |
+------------+---------------+------------------+
+ | 26.07 | 0.0.780 | 2.2 |
+ +------------+---------------+------------------+
Configuration
--
2.47.1
^ permalink raw reply related
* [PATCH v3] dts: update test suite names to be clear and consistent
From: Andrew Bailey @ 2026-05-08 14:13 UTC (permalink / raw)
To: luca.vizzarro, patrickrobb1997
Cc: lylavoie, ahassick, knimoji, dev, Andrew Bailey
In-Reply-To: <20251218150718.738116-1-abailey@iol.unh.edu>
Some test suites were prefixed with PMD which is not meaningful.
Other test suites used inconsistent naming schemes which this patch
makes uniform. For example, some suites had abbreviated words that
others had not. These words are no longer abbreviated among any test
suite.
Bugzilla ID: 1826
Signed-off-by: Andrew Bailey <abailey@iol.unh.edu>
---
doc/api/dts/tests.TestSuite_buffer_scatter.rst | 8 ++++++++
doc/api/dts/tests.TestSuite_flow_offload.rst | 8 ++++++++
...uite_virtio_fwd.rst => tests.TestSuite_l2_forward.rst} | 4 ++--
doc/api/dts/tests.TestSuite_pmd_buffer_scatter.rst | 8 --------
| 8 --------
doc/api/dts/tests.TestSuite_queue_start_stop.rst | 8 --------
doc/api/dts/tests.TestSuite_queue_toggle.rst | 8 ++++++++
| 6 +++---
doc/api/dts/tests.TestSuite_rte_flow.rst | 8 --------
doc/api/dts/tests.TestSuite_uni_pkt.rst | 8 --------
doc/api/dts/tests.TestSuite_unified_packet.rst | 8 ++++++++
doc/api/dts/tests.TestSuite_virtio_forward.rst | 8 ++++++++
..._pmd_buffer_scatter.py => TestSuite_buffer_scatter.py} | 2 +-
.../{TestSuite_rte_flow.py => TestSuite_flow_offload.py} | 4 ++--
dts/tests/{TestSuite_l2fwd.py => TestSuite_l2_forward.py} | 2 +-
...uite_queue_start_stop.py => TestSuite_queue_toggle.py} | 2 +-
| 4 ++--
.../{TestSuite_uni_pkt.py => TestSuite_unified_packet.py} | 2 +-
...estSuite_virtio_fwd.py => TestSuite_virtio_forward.py} | 2 +-
19 files changed, 54 insertions(+), 54 deletions(-)
create mode 100644 doc/api/dts/tests.TestSuite_buffer_scatter.rst
create mode 100644 doc/api/dts/tests.TestSuite_flow_offload.rst
rename doc/api/dts/{tests.TestSuite_virtio_fwd.rst => tests.TestSuite_l2_forward.rst} (60%)
delete mode 100644 doc/api/dts/tests.TestSuite_pmd_buffer_scatter.rst
delete mode 100644 doc/api/dts/tests.TestSuite_pmd_rss.rst
delete mode 100644 doc/api/dts/tests.TestSuite_queue_start_stop.rst
create mode 100644 doc/api/dts/tests.TestSuite_queue_toggle.rst
rename doc/api/dts/{tests.TestSuite_l2fwd.rst => tests.TestSuite_rss.rst} (52%)
delete mode 100644 doc/api/dts/tests.TestSuite_rte_flow.rst
delete mode 100644 doc/api/dts/tests.TestSuite_uni_pkt.rst
create mode 100644 doc/api/dts/tests.TestSuite_unified_packet.rst
create mode 100644 doc/api/dts/tests.TestSuite_virtio_forward.rst
rename dts/tests/{TestSuite_pmd_buffer_scatter.py => TestSuite_buffer_scatter.py} (99%)
rename dts/tests/{TestSuite_rte_flow.py => TestSuite_flow_offload.py} (99%)
rename dts/tests/{TestSuite_l2fwd.py => TestSuite_l2_forward.py} (98%)
rename dts/tests/{TestSuite_queue_start_stop.py => TestSuite_queue_toggle.py} (99%)
rename dts/tests/{TestSuite_pmd_rss.py => TestSuite_rss.py} (99%)
rename dts/tests/{TestSuite_uni_pkt.py => TestSuite_unified_packet.py} (99%)
rename dts/tests/{TestSuite_virtio_fwd.py => TestSuite_virtio_forward.py} (99%)
diff --git a/doc/api/dts/tests.TestSuite_buffer_scatter.rst b/doc/api/dts/tests.TestSuite_buffer_scatter.rst
new file mode 100644
index 0000000000..ce764ff0d6
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_buffer_scatter.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+buffer_scatter Test Suite
+=========================
+
+.. automodule:: tests.TestSuite_buffer_scatter
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_flow_offload.rst b/doc/api/dts/tests.TestSuite_flow_offload.rst
new file mode 100644
index 0000000000..5fcd3f57c3
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_flow_offload.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+flow_offload Test Suite
+=======================
+
+.. automodule:: tests.TestSuite_flow_offload
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_virtio_fwd.rst b/doc/api/dts/tests.TestSuite_l2_forward.rst
similarity index 60%
rename from doc/api/dts/tests.TestSuite_virtio_fwd.rst
rename to doc/api/dts/tests.TestSuite_l2_forward.rst
index e40cc4ca2b..3570a1e101 100644
--- a/doc/api/dts/tests.TestSuite_virtio_fwd.rst
+++ b/doc/api/dts/tests.TestSuite_l2_forward.rst
@@ -1,8 +1,8 @@
.. SPDX-License-Identifier: BSD-3-Clause
-virtio_fwd Test Suite
+l2_forward Test Suite
=====================
-.. automodule:: tests.TestSuite_virtio_fwd
+.. automodule:: tests.TestSuite_l2_forward
:members:
:show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_pmd_buffer_scatter.rst b/doc/api/dts/tests.TestSuite_pmd_buffer_scatter.rst
deleted file mode 100644
index cdf30fd879..0000000000
--- a/doc/api/dts/tests.TestSuite_pmd_buffer_scatter.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-pmd_buffer_scatter Test Suite
-=============================
-
-.. automodule:: tests.TestSuite_pmd_buffer_scatter
- :members:
- :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_pmd_rss.rst b/doc/api/dts/tests.TestSuite_pmd_rss.rst
deleted file mode 100644
index 942fa5ebdc..0000000000
--- a/doc/api/dts/tests.TestSuite_pmd_rss.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-pmd_rss Test Suite
-==================
-
-.. automodule:: tests.TestSuite_pmd_rss
- :members:
- :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_queue_start_stop.rst b/doc/api/dts/tests.TestSuite_queue_start_stop.rst
deleted file mode 100644
index 87121676fb..0000000000
--- a/doc/api/dts/tests.TestSuite_queue_start_stop.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-queue_start_stop Test Suite
-===========================
-
-.. automodule:: tests.TestSuite_queue_start_stop
- :members:
- :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_queue_toggle.rst b/doc/api/dts/tests.TestSuite_queue_toggle.rst
new file mode 100644
index 0000000000..1d6345511f
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_queue_toggle.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+queue_toggle Test Suite
+=======================
+
+.. automodule:: tests.TestSuite_queue_toggle
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_l2fwd.rst b/doc/api/dts/tests.TestSuite_rss.rst
similarity index 52%
rename from doc/api/dts/tests.TestSuite_l2fwd.rst
rename to doc/api/dts/tests.TestSuite_rss.rst
index 5a0ca312e9..ecd8676b09 100644
--- a/doc/api/dts/tests.TestSuite_l2fwd.rst
+++ b/doc/api/dts/tests.TestSuite_rss.rst
@@ -1,8 +1,8 @@
.. SPDX-License-Identifier: BSD-3-Clause
-l2fwd Test Suite
-================
+rss Test Suite
+==============
-.. automodule:: tests.TestSuite_l2fwd
+.. automodule:: tests.TestSuite_rss
:members:
:show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_rte_flow.rst b/doc/api/dts/tests.TestSuite_rte_flow.rst
deleted file mode 100644
index eacbfd3a2a..0000000000
--- a/doc/api/dts/tests.TestSuite_rte_flow.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-rte_flow Test Suite
-===================
-
-.. automodule:: tests.TestSuite_rte_flow
- :members:
- :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_uni_pkt.rst b/doc/api/dts/tests.TestSuite_uni_pkt.rst
deleted file mode 100644
index 95c5a5a28b..0000000000
--- a/doc/api/dts/tests.TestSuite_uni_pkt.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-uni_pkt Test Suite
-==================
-
-.. automodule:: tests.TestSuite_uni_pkt
- :members:
- :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_unified_packet.rst b/doc/api/dts/tests.TestSuite_unified_packet.rst
new file mode 100644
index 0000000000..dddf12b18a
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_unified_packet.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+unified_packet Test Suite
+=========================
+
+.. automodule:: tests.TestSuite_unified_packet
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/tests.TestSuite_virtio_forward.rst b/doc/api/dts/tests.TestSuite_virtio_forward.rst
new file mode 100644
index 0000000000..9178c73be5
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_virtio_forward.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+virtio_forward Test Suite
+=========================
+
+.. automodule:: tests.TestSuite_virtio_forward
+ :members:
+ :show-inheritance:
diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_buffer_scatter.py
similarity index 99%
rename from dts/tests/TestSuite_pmd_buffer_scatter.py
rename to dts/tests/TestSuite_buffer_scatter.py
index 96da67ee7d..539082f2e4 100644
--- a/dts/tests/TestSuite_pmd_buffer_scatter.py
+++ b/dts/tests/TestSuite_buffer_scatter.py
@@ -35,7 +35,7 @@
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_SCATTER)
-class TestPmdBufferScatter(TestSuite):
+class TestBufferScatter(TestSuite):
"""DPDK PMD packet scattering test suite.
Configure the Rx queues to have mbuf data buffers
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_flow_offload.py
similarity index 99%
rename from dts/tests/TestSuite_rte_flow.py
rename to dts/tests/TestSuite_flow_offload.py
index 6255e4c36d..be11d09875 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_flow_offload.py
@@ -402,8 +402,8 @@ def generate(
@requires_nic_capability(NicCapability.FLOW_CTRL)
-class TestRteFlow(TestSuite):
- """RTE Flow test suite.
+class TestFlowOffload(TestSuite):
+ """Flow offload test suite.
This suite consists of 4 test cases:
1. Queue Action: Verifies queue actions with multi-protocol patterns
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2_forward.py
similarity index 98%
rename from dts/tests/TestSuite_l2fwd.py
rename to dts/tests/TestSuite_l2_forward.py
index 596b892730..95f9c62bdc 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2_forward.py
@@ -28,7 +28,7 @@
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
@requires_link_topology(LinkTopology.TWO_LINKS)
-class TestL2fwd(TestSuite):
+class TestL2Forward(TestSuite):
"""L2 forwarding test suite."""
#: The total number of packets to generate and send for forwarding.
diff --git a/dts/tests/TestSuite_queue_start_stop.py b/dts/tests/TestSuite_queue_toggle.py
similarity index 99%
rename from dts/tests/TestSuite_queue_start_stop.py
rename to dts/tests/TestSuite_queue_toggle.py
index e9048d4245..e4edc89123 100644
--- a/dts/tests/TestSuite_queue_start_stop.py
+++ b/dts/tests/TestSuite_queue_toggle.py
@@ -32,7 +32,7 @@
@requires_link_topology(LinkTopology.TWO_LINKS)
@requires_nic_capability(NicCapability.RUNTIME_RX_QUEUE_SETUP)
@requires_nic_capability(NicCapability.RUNTIME_TX_QUEUE_SETUP)
-class TestQueueStartStop(TestSuite):
+class TestQueueToggle(TestSuite):
"""DPDK Queue start/stop test suite.
Ensures Rx/Tx queue on a port can be disabled and enabled.
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_rss.py
similarity index 99%
rename from dts/tests/TestSuite_pmd_rss.py
rename to dts/tests/TestSuite_rss.py
index f6adf262c3..2747c8a36c 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_rss.py
@@ -55,8 +55,8 @@ class HashAlgorithm(StrEnum):
@requires_link_topology(LinkTopology.ONE_LINK)
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_RSS_HASH)
-class TestPmdRss(TestSuite):
- """PMD RSS test suite."""
+class TestRss(TestSuite):
+ """RSS test suite."""
config: Config
diff --git a/dts/tests/TestSuite_uni_pkt.py b/dts/tests/TestSuite_unified_packet.py
similarity index 99%
rename from dts/tests/TestSuite_uni_pkt.py
rename to dts/tests/TestSuite_unified_packet.py
index 222276ce67..fcc7f7fbbb 100644
--- a/dts/tests/TestSuite_uni_pkt.py
+++ b/dts/tests/TestSuite_unified_packet.py
@@ -31,7 +31,7 @@
from framework.test_suite import TestSuite, func_test
-class TestUniPkt(TestSuite):
+class TestUnifiedPacket(TestSuite):
"""DPDK Unified packet test suite.
This testing suite uses testpmd's verbose output hardware/software
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_forward.py
similarity index 99%
rename from dts/tests/TestSuite_virtio_fwd.py
rename to dts/tests/TestSuite_virtio_forward.py
index bdecdb76fd..6efaa4e156 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_forward.py
@@ -20,7 +20,7 @@
from framework.testbed_model.virtual_device import VirtualDevice
-class TestVirtioFwd(TestSuite):
+class TestVirtioForward(TestSuite):
"""Virtio forwarding test suite."""
virtio_user_vdev = VirtualDevice(
--
2.50.1
^ permalink raw reply related
* Re: [PATCH v1] dts: add ipgre test suite
From: Andrew Bailey @ 2026-05-08 14:36 UTC (permalink / raw)
To: luca.vizzarro, probb, dev; +Cc: dmarx, knimoji
In-Reply-To: <CABJ3N2VwFm307fhAOY-n5Y-MCnvjh0rAee24vUJrmqcdtja0dQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 33 bytes --]
Recheck-request: github-robot
>
[-- Attachment #2: Type: text/html, Size: 272 bytes --]
^ permalink raw reply
* Re: [PATCH v1 1/4] bus/pci: introduce PCIe TPH support
From: Stephen Hemminger @ 2026-05-08 15:00 UTC (permalink / raw)
To: Chengwen Feng; +Cc: thomas, dev, wathsala.vithanage
In-Reply-To: <20260508092855.51987-2-fengchengwen@huawei.com>
On Fri, 8 May 2026 17:28:52 +0800
Chengwen Feng <fengchengwen@huawei.com> wrote:
> + * Used with VFIO_PCI_TPH_GET_CAP operation to return device
> + * TLP Processing Hints (TPH) capabilities to userspace.
> + */
> +struct vfio_pci_tph_cap {
> + __u8 supported_modes;
> +#define VFIO_PCI_TPH_MODE_IV (1u << 0) /* Interrupt vector */
> +#define VFIO_PCI_TPH_MODE_DS (1u << 1) /* Device specific */
Use enum n
> + __u8 reserved0;
> + __u16 st_table_sz;
> + __u32 reserved;
> +};
__u8, __u32 are kernel style types don't use in DPDK API's
I hate reserved fields. They don't do what you think and
create more problems. You end up having to enforce that reserved == 0
and
^ permalink raw reply
* Re: [PATCH v1] dts: clean cryptodev environment after a test run
From: Andrew Bailey @ 2026-05-08 15:05 UTC (permalink / raw)
To: dev, luca.vizzarro, patrickrobb1997; +Cc: lylavoie, ahassick, knimoji
In-Reply-To: <20260507163659.40739-1-abailey@iol.unh.edu>
[-- Attachment #1: Type: text/plain, Size: 38 bytes --]
Recheck-request: iol-intel-Functional
[-- Attachment #2: Type: text/html, Size: 102 bytes --]
^ permalink raw reply
* Re: [PATCH v1] dts: add ipgre test suite
From: Andrew Bailey @ 2026-05-08 15:07 UTC (permalink / raw)
To: luca.vizzarro, probb, dev; +Cc: dmarx, knimoji
In-Reply-To: <20260327180232.443820-1-abailey@iol.unh.edu>
[-- Attachment #1: Type: text/plain, Size: 37 bytes --]
Recheck-request: github-robot: build
[-- Attachment #2: Type: text/html, Size: 58 bytes --]
^ permalink raw reply
* Re: [PATCH v2 0/6] fix process shared pthread mutexes
From: Stephen Hemminger @ 2026-05-08 16:39 UTC (permalink / raw)
To: dev
In-Reply-To: <20260414144246.110681-1-stephen@networkplumber.org>
On Tue, 14 Apr 2026 07:39:52 -0700
Stephen Hemminger <stephen@networkplumber.org> wrote:
> Several drivers and the ethdev layer initialize pthread mutexes
> in shared memory with default (process-private) attributes.
> This is undefined behavior when secondary processes use them.
>
> This series adds PTHREAD_PROCESS_SHARED to all affected mutexes.
> All are on control paths (firmware mailbox, hotplug, flow ops,
> PHY negotiation) where sleeping is acceptable.
>
> See POSIX spec:
> https://pubs.opengroup.org/onlinepubs/009696899/functions/pthread_mutexattr_getpshared.html
>
> Bugzilla ID: 662
>
> v2 - fix build on Windows which does not need this.
>
> Stephen Hemminger (6):
> ethdev: fix flow_ops_mutex for multi-process
> net/failsafe: fix hotplug_mutex for multi-process
> net/atlantic: fix mbox_mutex for multi-process
> net/axgbe: fix mutexes for multi-process
> net/bnxt: fix mutexes for multi-process
> net/hinic: fix mutexes for multi-process
>
> drivers/net/atlantic/atl_ethdev.c | 14 +++++++++++++-
> drivers/net/axgbe/axgbe_ethdev.c | 19 +++++++++++++++----
> drivers/net/bnxt/bnxt_ethdev.c | 11 ++++++-----
> drivers/net/bnxt/bnxt_txq.c | 3 ++-
> drivers/net/bnxt/bnxt_util.c | 13 +++++++++++++
> drivers/net/bnxt/bnxt_util.h | 2 ++
> drivers/net/bnxt/tf_ulp/bnxt_ulp.c | 2 +-
> drivers/net/bnxt/tf_ulp/bnxt_ulp_tf.c | 2 +-
> drivers/net/bnxt/tf_ulp/bnxt_ulp_tfc.c | 2 +-
> drivers/net/failsafe/failsafe.c | 15 ++++++++++++---
> drivers/net/hinic/base/hinic_compat.h | 13 ++++++++++++-
> lib/ethdev/ethdev_driver.c | 22 +++++++++++++++++++++-
> 12 files changed, 99 insertions(+), 19 deletions(-)
>
Applied to next-net with helper.
^ permalink raw reply
* Re: [PATCH v2] net/mlx5: add validation for indirect actions
From: Dariusz Sosnowski @ 2026-05-08 17:11 UTC (permalink / raw)
To: Rayane Boussanni; +Cc: dev, rasland
In-Reply-To: <20260417222104.66543-1-rboussanni@gmail.com>
Hi,
Please see comments below.
On Fri, Apr 17, 2026 at 06:21:04PM -0400, Rayane Boussanni wrote:
> This patch implements missing validation logic for RSS and Connection
> Tracking (ConnTrack) indirect actions in the Hardware Steering (HWS)
> flow engine.
>
> Previously, these actions were accepted without being validated
> against hardware capabilities, which could lead to unexpected behavior
> when applying flow rules. The specialist validation functions
> (mlx5_hw_validate_action_rss and mlx5_hw_validate_action_conntrack)
> already existed but were not wired up to the indirect action handler.
>
> The signature of flow_hw_validate_action_indirect was updated to
> include the actions template attributes (attr), allowing it to pass
> the necessary traffic direction context (ingress/egress/transfer)
> to the underlying validation specialists.
>
> Signed-off-by: Rayane Boussanni <rboussanni@gmail.com>
> ---
> drivers/net/mlx5/mlx5_flow_hw.c | 29 +++++++++++++++++++++++++++--
> 1 file changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
> index bca5b2769e..ec1cdbe1fa 100644
> --- a/drivers/net/mlx5/mlx5_flow_hw.c
> +++ b/drivers/net/mlx5/mlx5_flow_hw.c
> @@ -346,6 +346,21 @@ mlx5_flow_ct_init(struct rte_eth_dev *dev,
> uint32_t nb_conn_tracks,
> uint16_t nb_queue);
>
> +static int
> +mlx5_hw_validate_action_rss(struct rte_eth_dev *dev,
> + const struct rte_flow_action *action,
> + const struct rte_flow_action *mask,
> + const struct rte_flow_actions_template_attr *attr,
> + uint64_t action_flags,
> + struct rte_flow_error *error);
> +static int
> +mlx5_hw_validate_action_conntrack(struct rte_eth_dev *dev,
> + const struct rte_flow_action *action,
> + const struct rte_flow_action *mask,
> + const struct rte_flow_actions_template_attr *attr,
> + uint64_t action_flags,
> + struct rte_flow_error *error);
> +
> static __rte_always_inline uint32_t flow_hw_tx_tag_regc_mask(struct rte_eth_dev *dev);
> static __rte_always_inline uint32_t flow_hw_tx_tag_regc_value(struct rte_eth_dev *dev);
>
> @@ -6604,6 +6619,8 @@ flow_hw_validate_action_meter_mark(struct rte_eth_dev *dev,
> * Pointer to the indirect action.
> * @param[in] mask
> * Pointer to the indirect action mask.
> + * @param[in] attr
> + * Pointer to the action template attributes.
> * @param[in, out] action_flags
> * Holds the actions detected until now.
> * @param[in, out] fixed_cnt
> @@ -6618,6 +6635,7 @@ static int
> flow_hw_validate_action_indirect(struct rte_eth_dev *dev,
> const struct rte_flow_action *action,
> const struct rte_flow_action *mask,
> + const struct rte_flow_actions_template_attr *attr,
> uint64_t *action_flags, bool *fixed_cnt,
> struct rte_flow_error *error)
> {
> @@ -6637,11 +6655,17 @@ flow_hw_validate_action_indirect(struct rte_eth_dev *dev,
> *action_flags |= MLX5_FLOW_ACTION_METER;
> break;
> case RTE_FLOW_ACTION_TYPE_RSS:
> - /* TODO: Validation logic (same as flow_hw_actions_validate) */
> + ret = mlx5_hw_validate_action_rss(dev, action, mask, attr,
> + *action_flags, error);
> + if (ret < 0)
> + return ret;
> *action_flags |= MLX5_FLOW_ACTION_RSS;
> break;
This change causes a segfault (see at [1] below).
mlx5_hw_validate_action_rss() and cannot be used here to validate
indirect RSS.
This function expects action param to contain valid action
configuration i.e., filled in rte_flow_action_rss struct.
For indirect actions, action->conf will contain opaque action handle
(pointer to rte_flow_action_handle).
RSS indirect action will be created before flow_hw_validate_action_indirect() is called
and it will already be validated (see flow_hw_action_handle_validate()).
In this function, it will be enough to check if attributes are good for RSS.
Could you please adjust mlx5_hw_validate_action_rss() to only validate
template's attributes for indirect actions?
> case RTE_FLOW_ACTION_TYPE_CONNTRACK:
> - /* TODO: Validation logic (same as flow_hw_actions_validate) */
> + ret = mlx5_hw_validate_action_conntrack(dev, action, mask, attr,
> + *action_flags, error);
> + if (ret < 0)
> + return ret;
> *action_flags |= MLX5_FLOW_ACTION_CT;
> break;
> case RTE_FLOW_ACTION_TYPE_COUNT:
> @@ -7352,6 +7376,7 @@ mlx5_flow_hw_actions_validate(struct rte_eth_dev *dev,
> case RTE_FLOW_ACTION_TYPE_INDIRECT:
> ret = flow_hw_validate_action_indirect(dev, action,
> mask,
> + attr,
> &action_flags,
> &fixed_cnt,
> error);
Best regards,
Dariusz Sosnowski
---
[1]: testpmd command line:
dpdk-testpmd -a 08:00.0,dv_flow_en=2 -- --flow-isolate-all --rxq=4 --txq=4 -i
testpmd commands:
port stop 0
flow configure 0 queues_number 4 queues_size 64
port start 0
flow queue 0 indirect_action 0 create ingress action_id 10 action rss func toeplitz types ipv4 end queues 0 1 2 3 end / end
flow push 0 queue 0
flow pull 0 queue 0
flow actions_template 0 create ingress actions_template_id 1000 template indirect 10 / end mask rss / end
segfault backtrace:
Thread 1 "dpdk-testpmd" received signal SIGSEGV, Segmentation fault.
0x0000555556aebb0c in mlx5_validate_action_rss (dev=0x55555a436a80 <rte_eth_devices>, action=0x7fffffff8718, error=0x7fffffff8560) at ../drivers/net/mlx5/mlx5_flow.c:2225
2225 if (rss->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) {
(gdb) bt
#0 0x0000555556aebb0c in mlx5_validate_action_rss (dev=0x55555a436a80 <rte_eth_devices>, action=0x7fffffff8718, error=0x7fffffff8560) at ../drivers/net/mlx5/mlx5_flow.c:2225
#1 0x000055555998f553 in mlx5_hw_validate_action_rss (dev=0x55555a436a80 <rte_eth_devices>, template_action=0x7fffffff8718, template_mask=0x7fffffff8738, template_attr=0x7fffffff85b4, action_flags=0, error=0x7fffffff8560) at ../drivers/net/mlx5/mlx5_flow_hw.c:7176
#2 0x000055555998e3ca in flow_hw_validate_action_indirect (dev=0x55555a436a80 <rte_eth_devices>, action=0x7fffffff8718, mask=0x7fffffff8738, attr=0x7fffffff85b4, action_flags=0x7fffffff78e0, fixed_cnt=0x7fffffff78d8, error=0x7fffffff8560)
at ../drivers/net/mlx5/mlx5_flow_hw.c:6658
#3 0x000055555998fd44 in mlx5_flow_hw_actions_validate (dev=0x55555a436a80 <rte_eth_devices>, attr=0x7fffffff85b4, actions=0x7fffffff8718, masks=0x7fffffff8738, act_flags=0x7fffffff79a8, error=0x7fffffff8560) at ../drivers/net/mlx5/mlx5_flow_hw.c:7377
#4 0x00005555599a0c71 in __flow_hw_actions_template_create (dev=0x55555a436a80 <rte_eth_devices>, attr=0x7fffffff85b4, actions=0x7fffffff8718, masks=0x7fffffff8738, nt_mode=false, error=0x7fffffff8560) at ../drivers/net/mlx5/mlx5_flow_hw.c:8149
#5 0x00005555599a1a48 in flow_hw_actions_template_create (dev=0x55555a436a80 <rte_eth_devices>, attr=0x7fffffff85b4, actions=0x7fffffff8718, masks=0x7fffffff8738, error=0x7fffffff8560) at ../drivers/net/mlx5/mlx5_flow_hw.c:8372
#6 0x0000555556b4e6c1 in mlx5_flow_actions_template_create (dev=0x55555a436a80 <rte_eth_devices>, attr=0x7fffffff85b4, actions=0x7fffffff8718, masks=0x7fffffff8738, error=0x7fffffff8560) at ../drivers/net/mlx5/mlx5_flow.c:9496
#7 0x0000555556890e21 in rte_flow_actions_template_create (port_id=0, template_attr=0x7fffffff85b4, actions=0x7fffffff8718, masks=0x7fffffff8738, error=0x7fffffff8560) at ../lib/ethdev/rte_flow.c:1908
#8 0x00005555557335d6 in port_flow_actions_template_create (port_id=0, id=1000, attr=0x7fffffff85b4, actions=0x7fffffff8718, masks=0x7fffffff8738) at ../app/test-pmd/config.c:2545
#9 0x0000555555681a97 in cmd_flow_parsed (in=0x7fffffff8670) at ../app/test-pmd/cmdline_flow.c:13410
#10 0x00005555556823d5 in cmd_flow_cb (arg0=0x7fffffff8670, cl=0x55555a6f4a50, arg2=0x0) at ../app/test-pmd/cmdline_flow.c:13634
#11 0x00005555567df3ae in __cmdline_parse (cl=0x55555a6f4a50, buf=0x55555a6f4a98 "flow actions_template 0 create ingress actions_template_id 1000 template indirect 10 / end mask rss / end\n", call_fn=true) at ../lib/cmdline/cmdline_parse.c:296
#12 0x00005555567df3f6 in cmdline_parse (cl=0x55555a6f4a50, buf=0x55555a6f4a98 "flow actions_template 0 create ingress actions_template_id 1000 template indirect 10 / end mask rss / end\n") at ../lib/cmdline/cmdline_parse.c:305
#13 0x00005555567dd719 in cmdline_valid_buffer (rdl=0x55555a6f4a60, buf=0x55555a6f4a98 "flow actions_template 0 create ingress actions_template_id 1000 template indirect 10 / end mask rss / end\n", size=107) at ../lib/cmdline/cmdline.c:25
#14 0x00005555567e28f5 in rdline_char_in (rdl=0x55555a6f4a60, c=10 '\n') at ../lib/cmdline/cmdline_rdline.c:470
#15 0x00005555567ddb6f in cmdline_in (cl=0x55555a6f4a50, buf=0x7fffffffe7b7 "\n", size=1) at ../lib/cmdline/cmdline.c:154
#16 0x00005555567ddd24 in cmdline_interact (cl=0x55555a6f4a50) at ../lib/cmdline/cmdline.c:202
#17 0x000055555567469b in cmdline_read_from_file (filename=0x55555a03de00 <cmdline_files> "indirect-rss-segfault.txt", echo=true) at ../app/test-pmd/cmdline.c:14550
#18 0x00005555557bc83c in main (argc=6, argv=0x7fffffffea70) at ../app/test-pmd/testpmd.c:4780
(gdb) p rss
$1 = (const void *) 0x1
^ permalink raw reply
* Re: [PATCH] net/mlx5: fallback to verbs for Tx memory allocation if devx unsupported
From: Dariusz Sosnowski @ 2026-05-08 17:18 UTC (permalink / raw)
To: banoth.saikumar; +Cc: viacheslavo, bingz, dev, stable
In-Reply-To: <20260323113403.1984-1-banoth.saikumar@oracle.com>
Hi,
Thank you for the contribution. Please see below.
On Mon, Mar 23, 2026 at 05:04:02PM +0530, banoth.saikumar@oracle.com wrote:
> From: Banoth Saikumar <banoth.saikumar@oracle.com>
>
> Previously, the mlx5 PMD attempted to allocate consecutive Tx memory
> using DevX without checking whether the NIC actually supported DevX.
> This led to allocation failures on legacy or unsupported NICs.
>
> This patch adds a fallback mechanism: if DevX is not available, the PMD
> skips DevX-based allocation and allows the verbs path to handle memory
> allocation and registration. This improves compatibility with older
> NICs and ensures Tx queue setup proceeds correctly.
>
> Fixes: bbfab2eb2528 ("net/mlx5: allocate and release unique
> resources for Tx queues")
> Cc: stable@dpdk.org
>
> Signed-off-by: Banoth Saikumar <banoth.saikumar@oracle.com>
> ---
> drivers/net/mlx5/mlx5_trigger.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
> index 6c6f228..c9ce3d4 100644
> --- a/drivers/net/mlx5/mlx5_trigger.c
> +++ b/drivers/net/mlx5/mlx5_trigger.c
> @@ -1161,7 +1161,7 @@ static int mlx5_dev_allocate_consec_tx_mem(struct rte_eth_dev *dev)
> void *umem_buf = NULL;
>
> /* Legacy per queue allocation, do nothing here. */
> - if (priv->sh->config.txq_mem_algn == 0)
> + if (priv->sh->config.txq_mem_algn == 0 || !priv->sh->cdev->config.devx)
Please use mlx5_devx_obj_ops_en() function instead of directly
checking priv->sh->cdev->config.devx field.
> return 0;
> alignment = (size_t)1 << priv->sh->config.txq_mem_algn;
> total_size = priv->consec_tx_mem.sq_total_size + priv->consec_tx_mem.cq_total_size;
Best regards,
Dariusz Sosnowski
^ permalink raw reply
* Re: [PATCH 25/25] doc: add BPF validate debug to programmer's guide
From: Stephen Hemminger @ 2026-05-08 17:41 UTC (permalink / raw)
To: Marat Khalili; +Cc: Konstantin Ananyev, dev
In-Reply-To: <20260506173846.64914-26-marat.khalili@huawei.com>
On Wed, 6 May 2026 18:38:43 +0100
Marat Khalili <marat.khalili@huawei.com> wrote:
> Document the new gdb-like validation debugger API, outlining how it can
> be used to set breakpoints and inspect register states during
> validation.
>
> Highlight its primary use case: writing robust tests for the eBPF
> verifier using the harness in app/test/test_bpf_validate.c.
>
> Signed-off-by: Marat Khalili <marat.khalili@huawei.com>
> ---
Regular AI review doesn't dig deep enough on this; so redid it with
stronger model and prompt.
Reviewed the series. It cannot be applied as-is for two compounding
reasons; once those are resolved, the individual fixes look correct
and well-tested.
Series-level: the patches reference rte_bpf_prm_ex, enum rte_bpf_origin
(RTE_BPF_ORIGIN_RAW), rte_bpf_load_ex, and rte_bpf_get_jit_ex. None of
these exist in upstream master, and none are introduced by this 25-patch
series — diff context in patch 5 (struct rte_bpf_prm_ex { hunk header)
and patch 2 (rte_bpf_get_jit_ex near the insertion point) confirms the
prerequisite must already be in the base. Please declare the dependency
in a 0/25 cover letter so reviewers can apply on the right base.
Patches 03, 05, 10: Build break. RTE_BPF_LOG_FUNC_LINE is used (replacing
RTE_BPF_LOG_LINE) but never defined — not in bpf_impl.h, not elsewhere in
DPDK, not in any of the 25 patches (verified by grep). Either add the
macro to bpf_impl.h, e.g.
#define RTE_BPF_LOG_FUNC_LINE(lvl, ...) \
RTE_LOG_LINE_PREFIX(lvl, BPF, "%s(): ", \
__func__ RTE_LOG_COMMA __VA_ARGS__)
following the pattern in lib/eal/common/eal_trace.h, or revert the call
sites to RTE_BPF_LOG_LINE(... "%s: ...", __func__, ...).
Patch 05: __rte_bpf_validate_state_is_valid and
__rte_bpf_validate_can_access return int but mix tri-state (true / false
/ -errno) with bool semantics; the caller does `if (rc == false)`
against an int. Works, but consider splitting the bool case from the
tri-state case for clarity.
Patch 08: Test file uses rte_bpf_load_ex, struct rte_bpf_prm_ex, and
RTE_BPF_ORIGIN_RAW (see series-level note). Two minor items in the test
helpers: load_constant / compare_and_jump assign int64_t to .imm
(int32_t) — fits_in_imm32() guards the value but an explicit (int32_t)
cast would document intent; and `value >> 32` on int64_t is
implementation-defined for negative values, a (uint64_t) cast before
the shift would be portable.
Patch 17: RTE_BPF_VALIDATE_DEBUG_EVENT_BRANCH_UNREACHABLE is inserted in
the middle of the enum, shifting BRANCH_RETURN and the _END sentinel.
Fine for an unreleased experimental API in the same series. Once the API
stabilizes, additions should go at the end before the sentinel.
Patches 01, 02, 04, 06, 07, 09, 11–16, 18, 19: no comments. The bug
descriptions with reproducer programs, expected-vs-actual output, and
UBSan diagnostics are very useful and the fixes are well-targeted.
I did not get to patches 20–25 in this pass.
^ permalink raw reply
* Re: [PATCH 0/3] net/bond: fix secondary process crash and related cleanup
From: Stephen Hemminger @ 2026-05-08 17:59 UTC (permalink / raw)
To: dev; +Cc: Chas Williams, Min Hu (Connor)
In-Reply-To: <20260417165530.653328-1-stephen@networkplumber.org>
On Fri, 17 Apr 2026 09:51:34 -0700
Stephen Hemminger <stephen@networkplumber.org> wrote:
> Patch 1 fixes the 8023ad dedicated-queue APIs which ignored the return
> of bond_ethdev_mode_set() and left the enabled flag inconsistent on
> failure. Ordered first so the secondary guard added next does not
> leave shared state corrupted.
>
> Patch 2 fixes the secondary process crash: a bonding port attached in
> a secondary crashes on the first Rx or Tx burst because the probe
> path never installs burst functions. Blackhole stubs are installed
> and mode changes from secondary are rejected. Fully sharing bonding
> state across processes is out of scope.
>
> Patch 3 drops redundant %s/func from log call sites now that
> RTE_BOND_LOG supplies the prefix.
>
> Stephen Hemminger (3):
> net/bonding: restore dedicated queue state on mode set error
> net/bonding: prevent crash on Rx/Tx from secondary process
> net/bonding: remove redundant function names from log
>
> drivers/net/bonding/rte_eth_bond_8023ad.c | 19 ++++---
> drivers/net/bonding/rte_eth_bond_api.c | 4 +-
> drivers/net/bonding/rte_eth_bond_pmd.c | 66 ++++++++++++++++++-----
> 3 files changed, 66 insertions(+), 23 deletions(-)
>
Would like review of this before adding to next-net
^ permalink raw reply
* [PATCH v2 0/4] net/axgbe: fix resource leaks and OOB access
From: Stephen Hemminger @ 2026-05-08 19:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
In-Reply-To: <20260218164324.915065-1-stephen@networkplumber.org>
Code review of the axgbe PMD identified several correctness bugs,
primarily around resource management on error paths in device
initialization and an out-of-bounds descriptor ring access.
Patch 1 fixes multiple resource leak paths in eth_axgbe_dev_init():
- mac_addrs leaked when hash_mac_addrs allocation fails
- hash_mac_addrs leaked when phy_init() fails
- rte_intr_callback_register() return value unchecked
- DMA reset failure via hw_if.exit() logged but not propagated
Patch 2 fixes wrapper_rx_desc_init() which only releases the
current queue on mbuf allocation failure, leaking all mbufs
from previously initialized queues.
Patch 3 adds pthread_mutex_destroy() calls in axgbe_dev_close()
for the four mutexes created during init.
Patch 4 fixes an out-of-bounds read in both Rx and Tx descriptor
status functions where desc[idx + offset] can exceed the ring
size. The offset is now folded into the index before masking.
v2:
- Patch 2: use rte_pktmbuf_alloc_bulk() instead of per-descriptor
allocation.
- Add Fixes: tags to all patches.
Stephen Hemminger (4):
net/axgbe: fix resource leaks in device init error paths
net/axgbe: fix Rx queue leak on descriptor init failure
net/axgbe: destroy mutexes on device close
net/axgbe: fix descriptor status out-of-bounds access
drivers/net/axgbe/axgbe_dev.c | 27 ++++++++++++---------------
drivers/net/axgbe/axgbe_ethdev.c | 26 ++++++++++++++++++++++++--
drivers/net/axgbe/axgbe_rxtx.c | 8 ++++----
3 files changed, 40 insertions(+), 21 deletions(-)
--
2.53.0
^ permalink raw reply
* [PATCH v2 1/4] net/axgbe: fix resource leaks in device init error paths
From: Stephen Hemminger @ 2026-05-08 19:10 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, stable, Selwin Sebastian, Ravi Kumar,
Chandubabu Namburu
In-Reply-To: <20260508191109.734377-1-stephen@networkplumber.org>
Several error paths in eth_axgbe_dev_init() fail to release
previously allocated resources:
- When hash_mac_addrs allocation fails, mac_addrs is leaked.
- When phy_init() fails, hash_mac_addrs is leaked.
- The return value of rte_intr_callback_register() is not
checked, so a failure leaves the driver without interrupt
handling but continuing as if everything is functional.
- When the DMA software reset via hw_if.exit() fails, the
error is only logged and initialization continues with the
hardware in an undefined state.
Fix all error paths to properly clean up previously allocated
resources, check the interrupt registration return value, and
propagate the DMA reset failure.
Fixes: e01d9b2e980b ("net/axgbe: support unicast hash table for MAC address")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/axgbe/axgbe_ethdev.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index cfcd880961..709a52acc8 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2359,6 +2359,8 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
PMD_INIT_LOG(ERR,
"Failed to allocate %d bytes needed to "
"store MAC addresses", len);
+ rte_free(eth_dev->data->mac_addrs);
+ eth_dev->data->mac_addrs = NULL;
return -ENOMEM;
}
@@ -2405,8 +2407,14 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
pdata->vdata->rx_max_fifo_size);
/* Issue software reset to DMA */
ret = pdata->hw_if.exit(pdata);
- if (ret)
+ if (ret) {
PMD_DRV_LOG_LINE(ERR, "hw_if->exit EBUSY error");
+ rte_free(eth_dev->data->hash_mac_addrs);
+ eth_dev->data->hash_mac_addrs = NULL;
+ rte_free(eth_dev->data->mac_addrs);
+ eth_dev->data->mac_addrs = NULL;
+ return ret;
+ }
/* Set default configuration data */
axgbe_default_config(pdata);
@@ -2426,14 +2434,23 @@ eth_axgbe_dev_init(struct rte_eth_dev *eth_dev)
ret = pdata->phy_if.phy_init(pdata);
if (ret) {
+ rte_free(eth_dev->data->hash_mac_addrs);
+ eth_dev->data->hash_mac_addrs = NULL;
rte_free(eth_dev->data->mac_addrs);
eth_dev->data->mac_addrs = NULL;
return ret;
}
- rte_intr_callback_register(pci_dev->intr_handle,
+ ret = rte_intr_callback_register(pci_dev->intr_handle,
axgbe_dev_interrupt_handler,
(void *)eth_dev);
+ if (ret) {
+ rte_free(eth_dev->data->hash_mac_addrs);
+ eth_dev->data->hash_mac_addrs = NULL;
+ rte_free(eth_dev->data->mac_addrs);
+ eth_dev->data->mac_addrs = NULL;
+ return ret;
+ }
PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x",
eth_dev->data->port_id, pci_dev->id.vendor_id,
pci_dev->id.device_id);
--
2.53.0
^ permalink raw reply related
* [PATCH v2 2/4] net/axgbe: fix Rx queue leak on descriptor init failure
From: Stephen Hemminger @ 2026-05-08 19:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, stable, Selwin Sebastian, Ravi Kumar
In-Reply-To: <20260508191109.734377-1-stephen@networkplumber.org>
When wrapper_rx_desc_init() fails to allocate an mbuf for queue i,
only queue i is released. Queues 0 through i-1 have already been
fully populated with mbufs assigned to sw_ring entries and
programmed into hardware descriptors, but are never cleaned up.
This leaks all mbufs from the previously initialized queues.
Fix by allocating all needed buffers ahead of time with
rte_pktmbuf_alloc_bulk() and on failure unwind the queues
that are already setup.
Fixes: 7c4158a5b592 ("net/axgbe: add DMA programming and start/stop")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/axgbe/axgbe_dev.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 482d3d8062..9eabe0dfa8 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -1011,13 +1011,11 @@ static void wrapper_tx_desc_init(struct axgbe_port *pdata)
static int wrapper_rx_desc_init(struct axgbe_port *pdata)
{
- struct axgbe_rx_queue *rxq;
- struct rte_mbuf *mbuf;
volatile union axgbe_rx_desc *desc;
unsigned int i, j;
for (i = 0; i < pdata->eth_dev->data->nb_rx_queues; i++) {
- rxq = pdata->eth_dev->data->rx_queues[i];
+ struct axgbe_rx_queue *rxq = pdata->eth_dev->data->rx_queues[i];
/* Initialize software ring entries */
rxq->mbuf_alloc = 0;
@@ -1025,19 +1023,18 @@ static int wrapper_rx_desc_init(struct axgbe_port *pdata)
rxq->dirty = 0;
desc = AXGBE_GET_DESC_PT(rxq, 0);
+ if (!rte_pktmbuf_alloc_bulk(rxq->mb_pool, rxq->sw_ring, rxq->nb_desc)) {
+ PMD_DRV_LOG_LINE(ERR, "RX mbuf alloc failed queue_id = %u, nb_desc = %u",
+ i, rxq->nb_desc);
+ for (unsigned int k = 0; k < i; k++)
+ axgbe_dev_rx_queue_release(pdata->eth_dev, k);
+ return -ENOMEM;
+ }
+
for (j = 0; j < rxq->nb_desc; j++) {
- mbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
- if (mbuf == NULL) {
- PMD_DRV_LOG_LINE(ERR, "RX mbuf alloc failed queue_id = %u, idx = %d",
- (unsigned int)rxq->queue_id, j);
- axgbe_dev_rx_queue_release(pdata->eth_dev, i);
- return -ENOMEM;
- }
- rxq->sw_ring[j] = mbuf;
- /* Mbuf populate */
- mbuf->next = NULL;
- mbuf->data_off = RTE_PKTMBUF_HEADROOM;
- mbuf->nb_segs = 1;
+ struct rte_mbuf *mbuf = rxq->sw_ring[j];
+
+ /* mbuf is in reset state (nb_segs = 1, headroom, etc) */
mbuf->port = rxq->port_id;
desc->read.baddr =
rte_cpu_to_le_64(
--
2.53.0
^ permalink raw reply related
* [PATCH v2 3/4] net/axgbe: destroy mutexes on device close
From: Stephen Hemminger @ 2026-05-08 19:10 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, stable, Selwin Sebastian, Ravi Kumar
In-Reply-To: <20260508191109.734377-1-stephen@networkplumber.org>
Four pthread mutexes (xpcs_mutex, i2c_mutex, an_mutex, phy_mutex)
are initialized in eth_axgbe_dev_init() but never destroyed in
axgbe_dev_close(). This leaks kernel resources on every device
close/reopen cycle.
Add pthread_mutex_destroy() calls to the close path.
Fixes: 572890ef6625 ("net/axgbe: add structs for MAC init and reset")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/axgbe/axgbe_ethdev.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index 709a52acc8..c8414998b4 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2482,6 +2482,11 @@ axgbe_dev_close(struct rte_eth_dev *eth_dev)
/* Disable all interrupts in the hardware */
XP_IOWRITE(pdata, XP_INT_EN, 0x0);
+ pthread_mutex_destroy(&pdata->xpcs_mutex);
+ pthread_mutex_destroy(&pdata->i2c_mutex);
+ pthread_mutex_destroy(&pdata->an_mutex);
+ pthread_mutex_destroy(&pdata->phy_mutex);
+
return 0;
}
--
2.53.0
^ permalink raw reply related
* [PATCH v2 4/4] net/axgbe: fix descriptor status out-of-bounds access
From: Stephen Hemminger @ 2026-05-08 19:10 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, stable, Selwin Sebastian, Ravi Kumar,
Amaranath Somalapuram
In-Reply-To: <20260508191109.734377-1-stephen@networkplumber.org>
Both axgbe_dev_rx_descriptor_status() and
axgbe_dev_tx_descriptor_status() compute the descriptor address as
desc[idx + offset] where idx is the masked ring position. When
idx + offset >= nb_desc, this reads past the end of the
descriptor ring buffer.
Fix by incorporating the offset into the index before masking,
using AXGBE_GET_DESC_IDX() which wraps with (nb_desc - 1).
Fixes: 0962b6055c08 ("net/axgbe: support descriptor status")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/axgbe/axgbe_rxtx.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/axgbe/axgbe_rxtx.c b/drivers/net/axgbe/axgbe_rxtx.c
index 51a1aeb0b9..6f750d6ede 100644
--- a/drivers/net/axgbe/axgbe_rxtx.c
+++ b/drivers/net/axgbe/axgbe_rxtx.c
@@ -1205,8 +1205,8 @@ axgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
if (offset >= rxq->nb_desc - rxq->dirty)
return RTE_ETH_RX_DESC_UNAVAIL;
- idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur);
- desc = &rxq->desc[idx + offset];
+ idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur + offset);
+ desc = &rxq->desc[idx];
if (!AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, OWN))
return RTE_ETH_RX_DESC_DONE;
@@ -1228,8 +1228,8 @@ axgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
if (offset >= txq->nb_desc - txq->dirty)
return RTE_ETH_TX_DESC_UNAVAIL;
- idx = AXGBE_GET_DESC_IDX(txq, txq->dirty + txq->free_batch_cnt - 1);
- desc = &txq->desc[idx + offset];
+ idx = AXGBE_GET_DESC_IDX(txq, txq->dirty + txq->free_batch_cnt - 1 + offset);
+ desc = &txq->desc[idx];
if (!AXGMAC_GET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN))
return RTE_ETH_TX_DESC_DONE;
--
2.53.0
^ permalink raw reply related
* [PATCH 00/20] pktmbuf free bulk cleanups
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
Looking at one driver noticed that rte_pktmbuf_free_bulk
was not being used. That motivated me to make a coccinelle
script to do a tree wide cleanup.
Then noticed that callers were having to check for NULL
before calling rte_pktmbuf_free_bulk, so changed it to
handle NULL array similar to free() and rte_free().
Do another tree wide pass to fix that and catch some
other unnecessary null checks in code.
Stephen Hemminger (20):
devtools/cocci: add transform for rte_pktmbuf_free_bulk
eventdev: use rte_pktmbuf_free_bulk
gso: use rte_pktmbuf_free_bulk
ip_frag: use rte_pktmbuf_free_bulk
pipeline: use rte_pktmbuf_free_bulk
port: use rte_pktmbuf_free_bulk
net/af_xdp: use rte_pktmbuf_free_bulk
net/cnxk: use rte_pktmbuf_free_bulk
net/pfe: use rte_pktmbuf_free_bulk
net/virtio: use rte_pktmbuf_free_bulk
net/zxdh: use rte_pktmbuf_free_bulk
app/compress-perf: use rte_pktmbuf_free_bulk
mbuf: allow NULL array in rte_pktmbuf_free_bulk
net/zxdh: remove unnecessary null check
net/ice: remove unnecessary null check
net/bnxt: remove unnecessary null check
test: use rte_pktmbuf_free_bulk
app/test-dma-perf: remove unnecessary null check
app/test-compress-perf: remove unnecessary null check
examples: use rte_pktmbuf_free_bulk
.../comp_perf_test_common.c | 8 +--
app/test-compress-perf/main.c | 6 +-
app/test-dma-perf/benchmark.c | 6 +-
app/test/sample_packet_forward.c | 5 +-
app/test/test_distributor.c | 4 +-
app/test/test_dmadev.c | 6 +-
app/test/test_ipfrag.c | 4 +-
app/test/test_link_bonding.c | 13 ++---
app/test/test_pmd_perf.c | 3 +-
app/test/test_pmd_tap.c | 3 +-
app/test/test_reorder.c | 12 ++--
app/test/test_table_ports.c | 12 ++--
app/test/test_table_tables.c | 21 +++----
devtools/cocci/free_bulk.cocci | 57 +++++++++++++++++++
devtools/cocci/nullfree.cocci | 5 +-
doc/guides/rel_notes/release_26_07.rst | 5 ++
drivers/net/af_xdp/rte_eth_af_xdp.c | 3 +-
drivers/net/bnxt/tf_core/v3/tfo.c | 6 +-
drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c | 6 +-
drivers/net/cnxk/cnxk_ethdev.c | 5 +-
drivers/net/intel/ice/ice_dcf_sched.c | 6 +-
drivers/net/pfe/pfe_ethdev.c | 4 +-
drivers/net/virtio/virtio_rxtx.c | 20 +++----
drivers/net/zxdh/zxdh_np.c | 3 +-
drivers/net/zxdh/zxdh_queue.c | 7 +--
drivers/net/zxdh/zxdh_rxtx.c | 3 +-
examples/bbdev_app/main.c | 4 +-
examples/l2fwd-crypto/main.c | 4 +-
.../client_server_mp/mp_client/client.c | 7 +--
.../client_server_mp/mp_server/main.c | 5 +-
examples/ntb/ntb_fwd.c | 12 ++--
examples/packet_ordering/main.c | 5 +-
examples/server_node_efd/efd_node/node.c | 7 +--
examples/server_node_efd/efd_server/main.c | 5 +-
examples/vhost/main.c | 3 +-
lib/eventdev/rte_event_eth_tx_adapter.c | 4 +-
lib/gso/gso_common.c | 5 +-
lib/ip_frag/rte_ipv6_fragmentation.c | 4 +-
lib/mbuf/rte_mbuf.c | 3 +
lib/mbuf/rte_mbuf.h | 1 +
lib/pipeline/rte_pipeline.c | 4 +-
lib/port/rte_port_fd.c | 6 +-
lib/port/rte_swx_port_fd.c | 8 +--
lib/port/rte_swx_port_source_sink.c | 6 +-
44 files changed, 152 insertions(+), 174 deletions(-)
create mode 100644 devtools/cocci/free_bulk.cocci
--
2.53.0
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox