|SUCCESS| [v2,5/5] net/iavf: fix duplicate MAC addresses install
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Wed May 6 19:38:25 CEST 2026
Test-Label: ai-code-review
Test-Status: SUCCESS
https://dpdk.org/patch/163685
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-05-06
Reviewing patch series from David Marchand <david.marchand at redhat.com>
Commit: ethdev: skip VMDq pools unless configured
This series modifies VMDq handling in ethdev and drivers.
> diff --git a/drivers/net/cnxk/cnxk_ethdev_ops.c b/drivers/net/cnxk/cnxk_ethdev_ops.c
> index 49e77e49a6..75decf7098 100644
> --- a/drivers/net/cnxk/cnxk_ethdev_ops.c
> +++ b/drivers/net/cnxk/cnxk_ethdev_ops.c
> @@ -1240,7 +1240,6 @@ cnxk_nix_mc_addr_list_configure(struct rte_eth_dev *eth_dev, struct rte_ether_ad
> /* Update address in NIC data structure */
> rte_ether_addr_copy(&mc_addr_set[i], &data->mac_addrs[j]);
> rte_ether_addr_copy(&mc_addr_set[i], &dev->dmac_addrs[j]);
> - data->mac_pool_sel[j] = RTE_BIT64(0);
> }
Does the removal of mac_pool_sel assignment break multicast handling
when VMDq is configured? The code unconditionally processes all
mc_addr_set entries but now skips pool bitmap updates.
> diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> index 2edc7a362e..9577b7d848 100644
> --- a/lib/ethdev/rte_ethdev.c
> +++ b/lib/ethdev/rte_ethdev.c
[ ... ]
> @@ -1680,7 +1680,10 @@ eth_dev_mac_restore(struct rte_eth_dev *dev,
> continue;
>
> pool = 0;
> - pool_mask = dev->data->mac_pool_sel[i];
> + if ((dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) != 0)
> + pool_mask = dev->data->mac_pool_sel[i];
> + else
> + pool_mask = 1;
Does the implicit comparison against zero in the pool_mask & UINT64_C(1)
test below match coding style? The style guide recommends explicit
comparisons: (pool_mask & UINT64_C(1)) != 0.
[ ... ]
> @@ -5390,8 +5393,9 @@ rte_eth_dev_mac_addr_add(uint16_t port_id, struct rte_ether_addr *addr,
> uint32_t pool)
> {
> struct rte_eth_dev *dev;
> - int index;
> uint64_t pool_mask;
> + bool vmdq;
> + int index;
Regarding whitespace style: Does mixing int and bool in the declarations
match DPDK patterns? The style guide shows grouping by type then
declaration order.
[ ... ]
> @@ -5416,6 +5420,12 @@ rte_eth_dev_mac_addr_add(uint16_t port_id, struct rte_ether_addr *addr,
> RTE_ETHDEV_LOG_LINE(ERR, "Pool ID must be 0-%d", RTE_ETH_64_POOLS - 1);
> return -EINVAL;
> }
> + vmdq = (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) != 0;
> + if (!vmdq && pool != 0) {
> + RTE_ETHDEV_LOG_LINE(ERR, "Port %u: VMDq is not configured (pool %d)",
> + port_id, pool);
> + return -EINVAL;
> + }
Does the implicit comparison on vmdq comply with the coding style
requirement for explicit comparisons? Should be if (vmdq == false).
[ ... ]
> @@ -5425,7 +5435,7 @@ rte_eth_dev_mac_addr_add(uint16_t port_id, struct rte_ether_addr *addr,
> port_id);
> return -ENOSPC;
> }
> - } else {
> + } else if (vmdq) {
Does this condition change the behavior when vmdq is false? The original
code entered this branch when index >= 0, now it only enters when
vmdq is true. Is this correct?
[ ... ]
> @@ -5440,8 +5450,10 @@ rte_eth_dev_mac_addr_add(uint16_t port_id, struct rte_ether_addr *addr,
> /* Update address in NIC data structure */
> rte_ether_addr_copy(addr, &dev->data->mac_addrs[index]);
>
> - /* Update pool bitmap in NIC data structure */
> - dev->data->mac_pool_sel[index] |= RTE_BIT64(pool);
> + if (vmdq) {
> + /* Update pool bitmap in NIC data structure */
> + dev->data->mac_pool_sel[index] |= RTE_BIT64(pool);
> + }
Does adding this conditional bracket match the style guide section 3.1
which discourages single statement conditionals with braces?
[ ... ]
Commit: ethdev: announce VMDq capability
> diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
> index b677f9491d..0f783b9e98 100644
> --- a/drivers/net/bnxt/bnxt_ethdev.c
> +++ b/drivers/net/bnxt/bnxt_ethdev.c
> @@ -1214,7 +1214,8 @@ static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
>
> dev_info->speed_capa = bnxt_get_speed_capabilities(bp);
> dev_info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
> - RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
> + RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP |
> + RTE_ETH_DEV_CAPA_VMDQ;
Does the alignment of the RTE_ETH_DEV_CAPA_VMDQ line match the
surrounding lines? Appears correct.
[ ... ]
> diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
> index 9577b7d848..7ba539e796 100644
> --- a/lib/ethdev/rte_ethdev.c
> +++ b/lib/ethdev/rte_ethdev.c
[ ... ]
> @@ -1581,6 +1582,22 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
> goto rollback;
> }
>
> + if (!(dev_info.dev_capa & RTE_ETH_DEV_CAPA_VMDQ)) {
> + if ((dev_conf->rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG) != 0) {
> + RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u does not support VMDq rx mode",
> + port_id);
> + ret = -EINVAL;
> + goto rollback;
> + }
> + if (dev_conf->txmode.mq_mode == RTE_ETH_MQ_TX_VMDQ_DCB ||
> + dev_conf->txmode.mq_mode == RTE_ETH_MQ_TX_VMDQ_ONLY) {
> + RTE_ETHDEV_LOG_LINE(ERR, "Ethdev port_id=%u does not support VMDq tx mode",
> + port_id);
> + ret = -EINVAL;
> + goto rollback;
> + }
> + }
Does the implicit comparison in the outer if statement follow the coding
style? Should be: if ((dev_info.dev_capa & RTE_ETH_DEV_CAPA_VMDQ) == 0).
[ ... ]
Commit: net/iavf: accept up to 32k unicast MAC addresses
> diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
> index 403c61e2e8..f1dede0694 100644
> --- a/drivers/net/intel/iavf/iavf.h
> +++ b/drivers/net/intel/iavf/iavf.h
> @@ -31,7 +31,8 @@
> #define IAVF_IRQ_MAP_NUM_PER_BUF 128
> #define IAVF_RXTX_QUEUE_CHUNKS_NUM 2
>
> -#define IAVF_NUM_MACADDR_MAX 64
> +#define IAVF_UC_MACADDR_MAX 32768
> +#define IAVF_MC_MACADDR_MAX 64
Does changing IAVF_NUM_MACADDR_MAX to IAVF_UC_MACADDR_MAX maintain API
compatibility? Are there external users of this define?
[ ... ]
> diff --git a/drivers/net/intel/iavf/iavf_vchnl.c b/drivers/net/intel/iavf/iavf_vchnl.c
> index 08dd6f2d7f..144968db35 100644
> --- a/drivers/net/intel/iavf/iavf_vchnl.c
> +++ b/drivers/net/intel/iavf/iavf_vchnl.c
[ ... ]
> @@ -1437,48 +1437,101 @@ iavf_config_irq_map_lv(struct iavf_adapter *adapter, uint16_t num)
> return 0;
> }
>
> -void
> -iavf_add_del_all_mac_addr(struct iavf_adapter *adapter, bool add)
> +static int
> +iavf_add_del_uc_addr_bulk(struct iavf_adapter *adapter, struct rte_ether_addr *addrs,
> + uint32_t nb_addrs, bool add)
> {
> +#define IAVF_ETH_ADDR_PER_REQ \
> + ((IAVF_AQ_BUF_SZ - sizeof(struct virtchnl_ether_addr_list)) / \
> + sizeof(struct virtchnl_ether_addr))
> struct {
> struct virtchnl_ether_addr_list list;
> - struct virtchnl_ether_addr addr[IAVF_NUM_MACADDR_MAX];
> - } list_req = {0};
> - struct virtchnl_ether_addr_list *list = &list_req.list;
> + struct virtchnl_ether_addr addr[IAVF_ETH_ADDR_PER_REQ];
> + } cmd_buffer;
Does the cmd_buffer lack initialization? The original list_req had = {0}.
Does this code leak uninitialized padding in the struct to the hardware?
> +#undef IAVF_ETH_ADDR_PER_REQ
> + struct virtchnl_ether_addr_list *list = &cmd_buffer.list;
> struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
> - struct iavf_cmd_info args = {0};
> - int err, i;
> - size_t buf_len;
>
> - for (i = 0; i < IAVF_NUM_MACADDR_MAX; i++) {
> - struct rte_ether_addr *addr = &adapter->dev_data->mac_addrs[i];
> - struct virtchnl_ether_addr *vc_addr = &list->list[list->num_elements];
> + for (uint32_t i = 0; i < nb_addrs; i++) {
> + size_t buf_len = sizeof(struct virtchnl_ether_addr_list) +
> + sizeof(struct virtchnl_ether_addr) * list->num_elements;
> + struct iavf_cmd_info args;
> + uint32_t batch;
> + int err;
>
> - /* ignore empty addresses */
> - if (rte_is_zero_ether_addr(addr))
> - continue;
> + batch = i % RTE_DIM(cmd_buffer.addr);
> +
> + if (batch == 0) {
> + memset(&cmd_buffer, 0, sizeof(cmd_buffer));
> + list->vsi_id = vf->vsi_res->vsi_id;
> + list->num_elements = 0;
> + }
Does this logic properly handle the case when nb_addrs is 0? Would it
dereference list->num_elements before initialization?
[ ... ]
> @@ -2060,7 +2113,7 @@ iavf_add_del_mc_addr_list(struct iavf_adapter *adapter,
> {
> struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
> uint8_t cmd_buffer[sizeof(struct virtchnl_ether_addr_list) +
> - (IAVF_NUM_MACADDR_MAX * sizeof(struct virtchnl_ether_addr))];
> + (IAVF_MC_MACADDR_MAX * sizeof(struct virtchnl_ether_addr))];
Does reducing the buffer size from 128 to 64 entries match the function
signature which still accepts up to mc_addr_num entries? Could this
overflow cmd_buffer?
[ ... ]
Commit: net/iavf: fix duplicate MAC addresses install
> diff --git a/drivers/net/intel/iavf/iavf_ethdev.c b/drivers/net/intel/iavf/iavf_ethdev.c
> index c69a012d50..5871ed3539 100644
> --- a/drivers/net/intel/iavf/iavf_ethdev.c
> +++ b/drivers/net/intel/iavf/iavf_ethdev.c
[ ... ]
> @@ -1039,15 +1049,14 @@ iavf_dev_start(struct rte_eth_dev *dev)
> rte_intr_enable(intr_handle);
> }
>
> - /* Set all mac addrs */
> - iavf_add_del_all_mac_addr(adapter, true);
> -
> - if (!adapter->mac_primary_set)
> - adapter->mac_primary_set = true;
> -
> - /* Set all multicast addresses */
More information about the test-report
mailing list