mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-05-26 11:40:24 +02:00
vdpa/mlx5: reuse common function for MAC address updates
Factor out MAC address update logic and reuse it from handle_ctrl_mac(). This ensures that old MAC entries are removed from the MPFS table before adding a new one and that the forwarding rules are updated accordingly. If updating the flow table fails, the original MAC and rules are restored as much as possible to keep the software and hardware state consistent. Signed-off-by: Cindy Lu <lulu@redhat.com> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260126094848.9601-3-lulu@redhat.com>
This commit is contained in:
committed by
Michael S. Tsirkin
parent
719d959274
commit
2f61e6eda7
@@ -2125,6 +2125,74 @@ static void teardown_steering(struct mlx5_vdpa_net *ndev)
|
||||
mlx5_destroy_flow_table(ndev->rxft);
|
||||
}
|
||||
|
||||
static int mlx5_vdpa_change_mac(struct mlx5_vdpa_net *ndev,
|
||||
struct mlx5_core_dev *pfmdev,
|
||||
const u8 *new_mac)
|
||||
{
|
||||
struct mlx5_vdpa_dev *mvdev = &ndev->mvdev;
|
||||
u8 old_mac[ETH_ALEN];
|
||||
|
||||
if (is_zero_ether_addr(new_mac))
|
||||
return -EINVAL;
|
||||
|
||||
if (!is_zero_ether_addr(ndev->config.mac)) {
|
||||
if (mlx5_mpfs_del_mac(pfmdev, ndev->config.mac)) {
|
||||
mlx5_vdpa_warn(mvdev, "failed to delete old MAC %pM from MPFS table\n",
|
||||
ndev->config.mac);
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (mlx5_mpfs_add_mac(pfmdev, (u8 *)new_mac)) {
|
||||
mlx5_vdpa_warn(mvdev, "failed to insert new MAC %pM into MPFS table\n",
|
||||
new_mac);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* backup the original mac address so that if failed to add the forward rules
|
||||
* we could restore it
|
||||
*/
|
||||
ether_addr_copy(old_mac, ndev->config.mac);
|
||||
|
||||
ether_addr_copy(ndev->config.mac, new_mac);
|
||||
|
||||
/* Need recreate the flow table entry, so that the packet could forward back
|
||||
*/
|
||||
mac_vlan_del(ndev, old_mac, 0, false);
|
||||
|
||||
if (mac_vlan_add(ndev, ndev->config.mac, 0, false)) {
|
||||
mlx5_vdpa_warn(mvdev, "failed to insert forward rules, try to restore\n");
|
||||
|
||||
/* Although it hardly run here, we still need double check */
|
||||
if (is_zero_ether_addr(old_mac)) {
|
||||
mlx5_vdpa_warn(mvdev, "restore mac failed: Original MAC is zero\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Try to restore original mac address to MFPS table, and try to restore
|
||||
* the forward rule entry.
|
||||
*/
|
||||
if (mlx5_mpfs_del_mac(pfmdev, ndev->config.mac)) {
|
||||
mlx5_vdpa_warn(mvdev, "restore mac failed: delete MAC %pM from MPFS table failed\n",
|
||||
ndev->config.mac);
|
||||
}
|
||||
|
||||
if (mlx5_mpfs_add_mac(pfmdev, old_mac)) {
|
||||
mlx5_vdpa_warn(mvdev, "restore mac failed: insert old MAC %pM into MPFS table failed\n",
|
||||
old_mac);
|
||||
}
|
||||
|
||||
ether_addr_copy(ndev->config.mac, old_mac);
|
||||
|
||||
if (mac_vlan_add(ndev, ndev->config.mac, 0, false))
|
||||
mlx5_vdpa_warn(mvdev, "restore forward rules failed: insert forward rules failed\n");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd)
|
||||
{
|
||||
struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
|
||||
@@ -2132,12 +2200,13 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd)
|
||||
virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
|
||||
struct mlx5_core_dev *pfmdev;
|
||||
size_t read;
|
||||
u8 mac[ETH_ALEN], mac_back[ETH_ALEN];
|
||||
u8 mac[ETH_ALEN];
|
||||
|
||||
pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev));
|
||||
switch (cmd) {
|
||||
case VIRTIO_NET_CTRL_MAC_ADDR_SET:
|
||||
read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->riov, (void *)mac, ETH_ALEN);
|
||||
read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->riov,
|
||||
(void *)mac, ETH_ALEN);
|
||||
if (read != ETH_ALEN)
|
||||
break;
|
||||
|
||||
@@ -2145,66 +2214,8 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd)
|
||||
status = VIRTIO_NET_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_zero_ether_addr(mac))
|
||||
break;
|
||||
|
||||
if (!is_zero_ether_addr(ndev->config.mac)) {
|
||||
if (mlx5_mpfs_del_mac(pfmdev, ndev->config.mac)) {
|
||||
mlx5_vdpa_warn(mvdev, "failed to delete old MAC %pM from MPFS table\n",
|
||||
ndev->config.mac);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mlx5_mpfs_add_mac(pfmdev, mac)) {
|
||||
mlx5_vdpa_warn(mvdev, "failed to insert new MAC %pM into MPFS table\n",
|
||||
mac);
|
||||
break;
|
||||
}
|
||||
|
||||
/* backup the original mac address so that if failed to add the forward rules
|
||||
* we could restore it
|
||||
*/
|
||||
memcpy(mac_back, ndev->config.mac, ETH_ALEN);
|
||||
|
||||
memcpy(ndev->config.mac, mac, ETH_ALEN);
|
||||
|
||||
/* Need recreate the flow table entry, so that the packet could forward back
|
||||
*/
|
||||
mac_vlan_del(ndev, mac_back, 0, false);
|
||||
|
||||
if (mac_vlan_add(ndev, ndev->config.mac, 0, false)) {
|
||||
mlx5_vdpa_warn(mvdev, "failed to insert forward rules, try to restore\n");
|
||||
|
||||
/* Although it hardly run here, we still need double check */
|
||||
if (is_zero_ether_addr(mac_back)) {
|
||||
mlx5_vdpa_warn(mvdev, "restore mac failed: Original MAC is zero\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Try to restore original mac address to MFPS table, and try to restore
|
||||
* the forward rule entry.
|
||||
*/
|
||||
if (mlx5_mpfs_del_mac(pfmdev, ndev->config.mac)) {
|
||||
mlx5_vdpa_warn(mvdev, "restore mac failed: delete MAC %pM from MPFS table failed\n",
|
||||
ndev->config.mac);
|
||||
}
|
||||
|
||||
if (mlx5_mpfs_add_mac(pfmdev, mac_back)) {
|
||||
mlx5_vdpa_warn(mvdev, "restore mac failed: insert old MAC %pM into MPFS table failed\n",
|
||||
mac_back);
|
||||
}
|
||||
|
||||
memcpy(ndev->config.mac, mac_back, ETH_ALEN);
|
||||
|
||||
if (mac_vlan_add(ndev, ndev->config.mac, 0, false))
|
||||
mlx5_vdpa_warn(mvdev, "restore forward rules failed: insert forward rules failed\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
status = VIRTIO_NET_OK;
|
||||
status = mlx5_vdpa_change_mac(ndev, pfmdev, mac) ? VIRTIO_NET_ERR :
|
||||
VIRTIO_NET_OK;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user