> Subject: [PATCH v7 2/4] net/iavf: fix duplicate MAC addresses install
>
> On port restart, all MAC addresses get pushed *twice* to the hardware,
> once by the driver and once by the eth_dev_mac_restore() in ethdev.
>
> On the other hand, MAC address filters are reset in the hardware
> by the PF only when a VF reset is triggered.
>
> Strictly speaking, the mac restore on port (re)start is unneeded,
> if no VF reset happened, so we can announce to ethdev that no mac
> restoration is needed via a get_restore_flags callback.
>
> Then, move the mac restoration to the VF reset handler.
>
> Fixes: 3d42086def30 ("net/iavf: preserve MAC address with i40e PF Linux
> driver")
> Cc: [email protected]
>
> Signed-off-by: David Marchand <[email protected]>
> ---
> Changes since v6:
> - renamed iavf_add_del_all_mac_addr and removed primary mac address
> handling out of this helper (avoids double primary mac installation),
>
> Changes since v4:
> - rebased on next-net-intel,
>
> Changes since v4:
> - moved mac restoration in iavf_post_reset_reconfig,
>
> ---
> drivers/net/intel/iavf/iavf.h | 2 +-
> drivers/net/intel/iavf/iavf_ethdev.c | 30 ++++++++++++++++++----------
> drivers/net/intel/iavf/iavf_vchnl.c | 11 +++++-----
> 3 files changed, 26 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
> index 1d52b3d113..34b9b4ad94 100644
> --- a/drivers/net/intel/iavf/iavf.h
> +++ b/drivers/net/intel/iavf/iavf.h
> @@ -482,7 +482,7 @@ int iavf_add_del_vlan_v2(struct iavf_adapter
> *adapter, uint16_t vlanid,
> int iavf_get_vlan_offload_caps_v2(struct iavf_adapter *adapter);
> int iavf_config_irq_map(struct iavf_adapter *adapter);
> int iavf_config_irq_map_lv(struct iavf_adapter *adapter, uint16_t num);
> -void iavf_add_del_all_mac_addr(struct iavf_adapter *adapter, bool add);
> +void iavf_add_del_secondary_mac_addr(struct iavf_adapter *adapter, bool
> add);
> int iavf_dev_link_update(struct rte_eth_dev *dev,
> __rte_unused int wait_to_complete);
> void iavf_dev_alarm_handler(void *param);
> diff --git a/drivers/net/intel/iavf/iavf_ethdev.c
> b/drivers/net/intel/iavf/iavf_ethdev.c
> index b498258d58..f7aeac8c83 100644
> --- a/drivers/net/intel/iavf/iavf_ethdev.c
> +++ b/drivers/net/intel/iavf/iavf_ethdev.c
> @@ -292,11 +292,12 @@ iavf_get_restore_flags(__rte_unused struct
> rte_eth_dev *dev,
> __rte_unused enum rte_eth_dev_operation op)
> {
> /*
> - * The unicast and multicast promiscuous settings persist across a
> + * The mac addresses, unicast and multicast promiscuous settings
> persist across a
> * stop/start; they are only cleared by a VF reset, which the driver
> * restores itself. So ethdev does not need to restore them on start.
> */
> - return RTE_ETH_RESTORE_ALL & ~(RTE_ETH_RESTORE_PROMISC |
> + return RTE_ETH_RESTORE_ALL & ~(RTE_ETH_RESTORE_MAC_ADDR |
> + RTE_ETH_RESTORE_PROMISC |
> RTE_ETH_RESTORE_ALLMULTI);
> }
>
> @@ -1095,15 +1096,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 */
> - iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf-
> >mc_addrs_num,
> - true);
> + if (!adapter->mac_primary_set) {
> + if (iavf_add_del_eth_addr(adapter, &dev->data-
> >mac_addrs[0], true,
> + VIRTCHNL_ETHER_ADDR_PRIMARY) != 0)
> + PMD_DRV_LOG(ERR, "failed to add primary MAC:"
> RTE_ETHER_ADDR_PRT_FMT,
> + RTE_ETHER_ADDR_BYTES(&dev->data-
> >mac_addrs[0]));
> + else
> + adapter->mac_primary_set = true;
> + }
>
> rte_spinlock_init(&vf->phc_time_aq_lock);
>
> @@ -3428,6 +3428,14 @@ iavf_post_reset_reconfig(struct rte_eth_dev
> *dev)
> int ret = 0;
> bool allmulti = false, allunicast = false;
> struct iavf_adapter *adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(dev-
> >data->dev_private);
> + struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data-
> >dev_private);
> +
> + /*
> + * After a VF reset, all MAC addresses got flushed.
> + * The primary MAC should have been set in iavf_dev_start, restore
iavf_dev_start is not guaranteed to have been executed before this handler.
So I would change this comment to something like:
"The primary MAC has been or will be restored by iavf_dev_start".
Other than that:
Acked-by: Ciara Loftus <[email protected]>
> the rest.
> + */
> + iavf_add_del_secondary_mac_addr(adapter, true);
> + (void)iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf-
> >mc_addrs_num, true);
>
> /* Restore pre-reset unicast promiscuous and multicast promiscuous
> states */
> if (dev->data->promiscuous)
> diff --git a/drivers/net/intel/iavf/iavf_vchnl.c
> b/drivers/net/intel/iavf/iavf_vchnl.c
> index df97ff2052..a918db5443 100644
> --- a/drivers/net/intel/iavf/iavf_vchnl.c
> +++ b/drivers/net/intel/iavf/iavf_vchnl.c
> @@ -1672,7 +1672,7 @@ iavf_config_irq_map_lv(struct iavf_adapter
> *adapter, uint16_t num)
> }
>
> void
> -iavf_add_del_all_mac_addr(struct iavf_adapter *adapter, bool add)
> +iavf_add_del_secondary_mac_addr(struct iavf_adapter *adapter, bool add)
> {
> struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
> struct {
> @@ -1685,7 +1685,7 @@ iavf_add_del_all_mac_addr(struct iavf_adapter
> *adapter, bool add)
> int err;
> size_t buf_len;
>
> - for (unsigned int i = 0; i < RTE_DIM(vf->mac_addrs); i++) {
> + for (unsigned int i = 1; i < RTE_DIM(vf->mac_addrs); i++) {
> struct rte_ether_addr *addr = &vf->mac_addrs[i];
> struct virtchnl_ether_addr *vc_addr = &list->list[list-
> >num_elements];
>
> @@ -1695,11 +1695,12 @@ iavf_add_del_all_mac_addr(struct iavf_adapter
> *adapter, bool add)
> list->num_elements++;
>
> memcpy(vc_addr->addr, addr->addr_bytes, sizeof(addr-
> >addr_bytes));
> - vc_addr->type = (list->num_elements == 1) ?
> - VIRTCHNL_ETHER_ADDR_PRIMARY :
> - VIRTCHNL_ETHER_ADDR_EXTRA;
> + vc_addr->type = VIRTCHNL_ETHER_ADDR_EXTRA;
> }
>
> + if (list->num_elements == 0)
> + return;
> +
> /* for some reason PF side checks for buffer being too big, so adjust it
> down */
> buf_len = sizeof(struct virtchnl_ether_addr_list) +
> sizeof(struct virtchnl_ether_addr) * list->num_elements;
> --
> 2.54.0