vdpa/mlx5: re-create forwarding rules after mac modified
authorMichael Qiu <qiudayu@archeros.com>
Mon, 28 Mar 2022 05:48:12 +0000 (01:48 -0400)
committerMichael S. Tsirkin <mst@redhat.com>
Mon, 28 Mar 2022 20:52:59 +0000 (16:52 -0400)
When MAC Address has been modified in guest, we only re-add the
Mac to mpfs, it is not enough, because the guest network will
not work correctly: the reply package from outside will go
straight away to the host VF net interface.

This patch recreate the flow rules, and make it work correctly.

Signed-off-by: Michael Qiu <qiudayu@archeros.com>
Link: https://lore.kernel.org/r/1648446492-17614-1-git-send-email-08005325@163.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Eli Cohen <elic@nvidia.com>
drivers/vdpa/mlx5/net/mlx5_vnet.c

index 5d7f3e8..c0f0ecb 100644 (file)
@@ -1475,7 +1475,7 @@ 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];
+       u8 mac[ETH_ALEN], mac_back[ETH_ALEN];
 
        pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev));
        switch (cmd) {
@@ -1489,6 +1489,9 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd)
                        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",
@@ -1503,7 +1506,47 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd)
                        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
+                */
+               remove_fwd_to_tir(ndev);
+
+               if (add_fwd_to_tir(ndev)) {
+                       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 (add_fwd_to_tir(ndev))
+                               mlx5_vdpa_warn(mvdev, "restore forward rules failed: insert forward rules failed\n");
+
+                       break;
+               }
+
                status = VIRTIO_NET_OK;
                break;