diff mbox

[3/3] IB/core: Fix deleting default GIDs when changing MAC address

Message ID 20180412222427.24882-4-leon@kernel.org (mailing list archive)
State Superseded
Headers show

Commit Message

Leon Romanovsky April 12, 2018, 10:24 p.m. UTC
From: Parav Pandit <parav@mellanox.com>

Before [1], when MAC address of the netdevice is changed, default GID is
supposed to get deleted and added back which affects the node and/or port
GUID in below sequence.

netdevice_event()
-> NETDEV_CHANGEADDR
   default_del_cmd()
      del_netdev_default_ips()
          bond_delete_netdev_default_gids()
              ib_cache_gid_set_default_gid()
                  ib_cache_gid_del()
   add_cmd()
   [..]

However, ib_cache_gid_del() was not getting invoked in non bonding
scenarios because event_ndev and rdma_ndev are same.
Therefore, fix such condition to ignore checking upper device when event
ndev and rdma_dev are same; similar to bond_set_netdev_default_gids().

Which this fix ib_cache_gid_del() is invoked correctly; however
ib_cache_gid_del() doesn't find the default GID for deletion because
find_gid() was given default_gid = false with GID_ATTR_FIND_MASK_DEFAULT
set. But it was getting overwritten by ib_cache_gid_set_default_gid()
later on as part of add_cmd(). Therefore, mac address change used
to work for default GID.

With refactor series [1], this incorrect behavior is detected.

Therefore,
when deleting default GID, set default_gid and set MASK flag.
when deleting IP based GID, clear default_gid and set MASK flag.

[1] https://patchwork.kernel.org/patch/10319151/

Fixes: 238fdf48f2b5 ("IB/core: Add RoCE table bonding support")
Fixes: 598ff6bae689 ("IB/core: Refactor GID modify code for RoCE")
Signed-off-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/cache.c         | 28 +++++++++++++++-------------
 drivers/infiniband/core/roce_gid_mgmt.c | 26 ++++++++++++++------------
 2 files changed, 29 insertions(+), 25 deletions(-)

--
2.14.3

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 23cdd198997b..df4219c7e211 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -428,7 +428,7 @@  int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
 static int
 _ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
 		  union ib_gid *gid, struct ib_gid_attr *attr,
-		  bool default_gid)
+		  unsigned long mask, bool default_gid)
 {
 	struct ib_gid_table *table;
 	int ret = 0;
@@ -438,12 +438,7 @@  _ib_cache_gid_del(struct ib_device *ib_dev, u8 port,

 	mutex_lock(&table->lock);

-	ix = find_gid(table, gid, attr, default_gid,
-		      GID_ATTR_FIND_MASK_GID	  |
-		      GID_ATTR_FIND_MASK_GID_TYPE |
-		      GID_ATTR_FIND_MASK_DEFAULT  |
-		      GID_ATTR_FIND_MASK_NETDEV,
-		      NULL);
+	ix = find_gid(table, gid, attr, default_gid, mask, NULL);
 	if (ix < 0) {
 		ret = -EINVAL;
 		goto out_unlock;
@@ -463,7 +458,12 @@  _ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
 int ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
 		     union ib_gid *gid, struct ib_gid_attr *attr)
 {
-	return _ib_cache_gid_del(ib_dev, port, gid, attr, false);
+	unsigned long mask = GID_ATTR_FIND_MASK_GID	  |
+			     GID_ATTR_FIND_MASK_GID_TYPE |
+			     GID_ATTR_FIND_MASK_DEFAULT  |
+			     GID_ATTR_FIND_MASK_NETDEV;
+
+	return _ib_cache_gid_del(ib_dev, port, gid, attr, mask, false);
 }

 int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port,
@@ -742,7 +742,7 @@  void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
 				  unsigned long gid_type_mask,
 				  enum ib_cache_gid_default_mode mode)
 {
-	union ib_gid gid;
+	union ib_gid gid = { };
 	struct ib_gid_attr gid_attr;
 	struct ib_gid_table *table;
 	unsigned int gid_type;
@@ -750,7 +750,9 @@  void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,

 	table = ib_dev->cache.ports[port - rdma_start_port(ib_dev)].gid;

-	make_default_gid(ndev, &gid);
+	mask = GID_ATTR_FIND_MASK_GID_TYPE |
+	       GID_ATTR_FIND_MASK_DEFAULT |
+	       GID_ATTR_FIND_MASK_NETDEV;
 	memset(&gid_attr, 0, sizeof(gid_attr));
 	gid_attr.ndev = ndev;

@@ -761,12 +763,12 @@  void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
 		gid_attr.gid_type = gid_type;

 		if (mode == IB_CACHE_GID_DEFAULT_MODE_SET) {
-			mask = GID_ATTR_FIND_MASK_GID_TYPE |
-			       GID_ATTR_FIND_MASK_DEFAULT;
+			make_default_gid(ndev, &gid);
 			__ib_cache_gid_add(ib_dev, port, &gid,
 					   &gid_attr, mask, true);
 		} else if (mode == IB_CACHE_GID_DEFAULT_MODE_DELETE) {
-			_ib_cache_gid_del(ib_dev, port, &gid, &gid_attr, true);
+			_ib_cache_gid_del(ib_dev, port, &gid,
+					  &gid_attr, mask, true);
 		}
 	}
 }
diff --git a/drivers/infiniband/core/roce_gid_mgmt.c b/drivers/infiniband/core/roce_gid_mgmt.c
index 5a52ec77940a..e3baf25fc9be 100644
--- a/drivers/infiniband/core/roce_gid_mgmt.c
+++ b/drivers/infiniband/core/roce_gid_mgmt.c
@@ -255,6 +255,7 @@  static void bond_delete_netdev_default_gids(struct ib_device *ib_dev,
 					    struct net_device *rdma_ndev)
 {
 	struct net_device *real_dev = rdma_vlan_dev_real_dev(event_ndev);
+	unsigned long gid_type_mask;

 	if (!rdma_ndev)
 		return;
@@ -264,21 +265,22 @@  static void bond_delete_netdev_default_gids(struct ib_device *ib_dev,

 	rcu_read_lock();

-	if (rdma_is_upper_dev_rcu(rdma_ndev, event_ndev) &&
-	    is_eth_active_slave_of_bonding_rcu(rdma_ndev, real_dev) ==
-	    BONDING_SLAVE_STATE_INACTIVE) {
-		unsigned long gid_type_mask;
-
+	if (((rdma_ndev != event_ndev &&
+	      !rdma_is_upper_dev_rcu(rdma_ndev, event_ndev)) ||
+	     is_eth_active_slave_of_bonding_rcu(rdma_ndev, real_dev)
+						 ==
+	     BONDING_SLAVE_STATE_INACTIVE)) {
 		rcu_read_unlock();
+		return;
+	}

-		gid_type_mask = roce_gid_type_mask_support(ib_dev, port);
+	rcu_read_unlock();

-		ib_cache_gid_set_default_gid(ib_dev, port, rdma_ndev,
-					     gid_type_mask,
-					     IB_CACHE_GID_DEFAULT_MODE_DELETE);
-	} else {
-		rcu_read_unlock();
-	}
+	gid_type_mask = roce_gid_type_mask_support(ib_dev, port);
+
+	ib_cache_gid_set_default_gid(ib_dev, port, rdma_ndev,
+				     gid_type_mask,
+				     IB_CACHE_GID_DEFAULT_MODE_DELETE);
 }

 static void enum_netdev_ipv4_ips(struct ib_device *ib_dev,