Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc5640f2 authored by Parav Pandit's avatar Parav Pandit Committed by Doug Ledford
Browse files

IB/core: Fix deleting default GIDs when changing mac adddress

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: 238fdf48 ("IB/core: Add RoCE table bonding support")
Fixes: 598ff6ba ("IB/core: Refactor GID modify code for RoCE")
Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 22c01ee4
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
@@ -427,7 +427,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;
@@ -437,12 +437,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;
@@ -462,7 +457,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,
@@ -741,7 +741,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;
@@ -749,7 +749,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;

@@ -760,12 +762,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);
		}
	}
}
+14 −12
Original line number Diff line number Diff line
@@ -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,10 +265,14 @@ 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;
	}

	rcu_read_unlock();

@@ -276,9 +281,6 @@ static void bond_delete_netdev_default_gids(struct ib_device *ib_dev,
	ib_cache_gid_set_default_gid(ib_dev, port, rdma_ndev,
				     gid_type_mask,
				     IB_CACHE_GID_DEFAULT_MODE_DELETE);
	} else {
		rcu_read_unlock();
	}
}

static void enum_netdev_ipv4_ips(struct ib_device *ib_dev,