net/mlx4_core: Replace VF zero mac with random mac in mlx4_core
authorJack Morgenstein <jackm@dev.mellanox.co.il>
Wed, 14 Oct 2015 14:43:48 +0000 (17:43 +0300)
committerDavid S. Miller <davem@davemloft.net>
Thu, 15 Oct 2015 02:14:44 +0000 (19:14 -0700)
By design, when no default MAC addresses are set in the Hypervisor for VFs,
the VFs are passed zero-macs. When such a MAC is received by the VF, it
generates a random MAC address and registers that MAC address
with the Hypervisor.

This random mac generation is currently done in the mlx4_en module.
There is a problem, though, if the mlx4_ib module is loaded by a VF before
the mlx4_en module. In this case, for RoCE, mlx4_ib will see the un-replaced
zero-mac and register that zero-mac as part of QP1 initialization.

Having a zero-mac in the port's MAC table creates problems for a
Baseboard Management Console. The BMC occasionally sends packets with a
zero-mac destination MAC. If there is a zero-mac present in the port's
MAC table, the FW will send such BMC packets to the host driver rather than
to the wire, and BMC will stop working.

To address this problem, we move the replacement of zero-mac addresses
with random-mac addresses to procedure mlx4_slave_cap(), which is part of the
driver startup for VFs, and is before activation of mlx4_ib and mlx4_en.
As a result, zero-mac addresses will never be registered in the port MAC table
by the driver.

In addition, when mlx4_en does initialize the net device, it needs to set
the NET_ADDR_RANDOM flag in the netdev structure if the address was
randomly generated. This is done so that udev on the VM does not create
a new device name after each VF probe (VM boot and such). To accomplish this,
we add a per-port flag in mlx4_dev which gets set whenever mlx4_core replaces
a zero-mac with a randomly-generated mac. This flag is examined when mlx4_en
initializes the net-device.

Fix was suggested by Matan Barak <matanb@mellanox.com>

Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
include/linux/mlx4/device.h

index 597d8923c8e1c9cb14deedba68e088e7fd4dc605..886e1bc86374d990fc92655c7e1b40a3d611b45c 100644 (file)
@@ -2816,7 +2816,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        struct mlx4_en_priv *priv;
        int i;
        int err;
-       u64 mac_u64;
 
        dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
                                 MAX_TX_RINGS, MAX_RX_RINGS);
@@ -2908,17 +2907,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        dev->addr_len = ETH_ALEN;
        mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]);
        if (!is_valid_ether_addr(dev->dev_addr)) {
-               if (mlx4_is_slave(priv->mdev->dev)) {
-                       eth_hw_addr_random(dev);
-                       en_warn(priv, "Assigned random MAC address %pM\n", dev->dev_addr);
-                       mac_u64 = mlx4_mac_to_u64(dev->dev_addr);
-                       mdev->dev->caps.def_mac[priv->port] = mac_u64;
-               } else {
-                       en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
-                              priv->port, dev->dev_addr);
-                       err = -EINVAL;
-                       goto out;
-               }
+               en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
+                      priv->port, dev->dev_addr);
+               err = -EINVAL;
+               goto out;
+       } else if (mlx4_is_slave(priv->mdev->dev) &&
+                  (priv->mdev->dev->port_random_macs & 1 << priv->port)) {
+               /* Random MAC was assigned in mlx4_slave_cap
+                * in mlx4_core module
+                */
+               dev->addr_assign_type |= NET_ADDR_RANDOM;
+               en_warn(priv, "Assigned random MAC address %pM\n", dev->dev_addr);
        }
 
        memcpy(priv->current_mac, dev->dev_addr, sizeof(priv->current_mac));
index e8ec1dec5789a8d80499e8c478e4822567480284..f13a4d7bbf9597535e5f6271dea3769389bc90b6 100644 (file)
@@ -2840,3 +2840,19 @@ int set_phv_bit(struct mlx4_dev *dev, u8 port, int new_val)
        return -EOPNOTSUPP;
 }
 EXPORT_SYMBOL(set_phv_bit);
+
+void mlx4_replace_zero_macs(struct mlx4_dev *dev)
+{
+       int i;
+       u8 mac_addr[ETH_ALEN];
+
+       dev->port_random_macs = 0;
+       for (i = 1; i <= dev->caps.num_ports; ++i)
+               if (!dev->caps.def_mac[i] &&
+                   dev->caps.port_type[i] == MLX4_PORT_TYPE_ETH) {
+                       eth_random_addr(mac_addr);
+                       dev->port_random_macs |= 1 << i;
+                       dev->caps.def_mac[i] = mlx4_mac_to_u64(mac_addr);
+               }
+}
+EXPORT_SYMBOL_GPL(mlx4_replace_zero_macs);
index 006757f80988bcb71cfc352542305b61310ef40f..bcbdfab1fe19b137f35046eddf87ae30847fd9e5 100644 (file)
@@ -863,6 +863,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
                return -ENODEV;
        }
 
+       mlx4_replace_zero_macs(dev);
+
        dev->caps.qp0_qkey = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL);
        dev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
        dev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL);
index 232b2b55f23b9170b32f351926c200b6ac0e7f1c..e1cf9036af225992c3961254cad0b474ca191e84 100644 (file)
@@ -1378,6 +1378,8 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work);
 
 void mlx4_init_quotas(struct mlx4_dev *dev);
 
+/* for VFs, replace zero MACs with randomly-generated MACs at driver start */
+void mlx4_replace_zero_macs(struct mlx4_dev *dev);
 int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port);
 /* Returns the VF index of slave */
 int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave);
index baad4cb8e9b065fb76c8e2b66379d9415d0f4e47..5a8677bafe0408bad140320471e38c100e4bf33a 100644 (file)
@@ -833,6 +833,7 @@ struct mlx4_dev {
        struct mlx4_quotas      quotas;
        struct radix_tree_root  qp_table_tree;
        u8                      rev_id;
+       u8                      port_random_macs;
        char                    board_id[MLX4_BOARD_ID_LEN];
        int                     numa_node;
        int                     oper_log_mgm_entry_size;