iavf: fix MAC address setting for VFs when filter is rejected
authorStefan Assmann <sassmann@kpanic.de>
Thu, 5 Sep 2019 06:34:22 +0000 (08:34 +0200)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 11 Sep 2019 16:10:46 +0000 (09:10 -0700)
Currently iavf unconditionally applies MAC address change requests. This
brings the VF in a state where it is no longer able to pass traffic if
the PF rejects a MAC filter change for the VF.
A typical scenario for a rejected MAC filter is for an untrusted VF to
request to change the MAC address when an administratively set MAC is
present.

To keep iavf working in this scenario the MAC filter handling in iavf
needs to act on the PF reply regarding the MAC filter change. In the
case of an ack the new MAC address gets set, whereas in the case of a
nack the previous MAC address needs to stay in place.

Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c

index 07f5541a0f01380a0933814e0724623ef4013a5b..8f310e520b069bd2903d7ee353238c84018201e0 100644 (file)
@@ -804,7 +804,6 @@ static int iavf_set_mac(struct net_device *netdev, void *p)
 
        if (f) {
                ether_addr_copy(hw->mac.addr, addr->sa_data);
-               ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
        }
 
        return (f == NULL) ? -ENOMEM : 0;
index d49d58a6de8035c57fc2c00b0d8713cef852c10e..c46770eba320e6b8a05d67e566db95da1636e506 100644 (file)
@@ -1252,6 +1252,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                case VIRTCHNL_OP_ADD_ETH_ADDR:
                        dev_err(&adapter->pdev->dev, "Failed to add MAC filter, error %s\n",
                                iavf_stat_str(&adapter->hw, v_retval));
+                       /* restore administratively set MAC address */
+                       ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
                        break;
                case VIRTCHNL_OP_DEL_VLAN:
                        dev_err(&adapter->pdev->dev, "Failed to delete VLAN filter, error %s\n",
@@ -1319,6 +1321,11 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                }
        }
        switch (v_opcode) {
+       case VIRTCHNL_OP_ADD_ETH_ADDR: {
+               if (!ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr))
+                       ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
+               }
+               break;
        case VIRTCHNL_OP_GET_STATS: {
                struct iavf_eth_stats *stats =
                        (struct iavf_eth_stats *)msg;