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

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
...@@ -427,7 +427,7 @@ int ib_cache_gid_add(struct ib_device *ib_dev, u8 port, ...@@ -427,7 +427,7 @@ int ib_cache_gid_add(struct ib_device *ib_dev, u8 port,
static int static int
_ib_cache_gid_del(struct ib_device *ib_dev, u8 port, _ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
union ib_gid *gid, struct ib_gid_attr *attr, union ib_gid *gid, struct ib_gid_attr *attr,
bool default_gid) unsigned long mask, bool default_gid)
{ {
struct ib_gid_table *table; struct ib_gid_table *table;
int ret = 0; int ret = 0;
...@@ -437,12 +437,7 @@ _ib_cache_gid_del(struct ib_device *ib_dev, u8 port, ...@@ -437,12 +437,7 @@ _ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
mutex_lock(&table->lock); mutex_lock(&table->lock);
ix = find_gid(table, gid, attr, default_gid, ix = find_gid(table, gid, attr, default_gid, mask, NULL);
GID_ATTR_FIND_MASK_GID |
GID_ATTR_FIND_MASK_GID_TYPE |
GID_ATTR_FIND_MASK_DEFAULT |
GID_ATTR_FIND_MASK_NETDEV,
NULL);
if (ix < 0) { if (ix < 0) {
ret = -EINVAL; ret = -EINVAL;
goto out_unlock; goto out_unlock;
...@@ -462,7 +457,12 @@ _ib_cache_gid_del(struct ib_device *ib_dev, u8 port, ...@@ -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, int ib_cache_gid_del(struct ib_device *ib_dev, u8 port,
union ib_gid *gid, struct ib_gid_attr *attr) 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, 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, ...@@ -741,7 +741,7 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
unsigned long gid_type_mask, unsigned long gid_type_mask,
enum ib_cache_gid_default_mode mode) enum ib_cache_gid_default_mode mode)
{ {
union ib_gid gid; union ib_gid gid = { };
struct ib_gid_attr gid_attr; struct ib_gid_attr gid_attr;
struct ib_gid_table *table; struct ib_gid_table *table;
unsigned int gid_type; unsigned int gid_type;
...@@ -749,7 +749,9 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port, ...@@ -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; 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)); memset(&gid_attr, 0, sizeof(gid_attr));
gid_attr.ndev = ndev; gid_attr.ndev = ndev;
...@@ -760,12 +762,12 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port, ...@@ -760,12 +762,12 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
gid_attr.gid_type = gid_type; gid_attr.gid_type = gid_type;
if (mode == IB_CACHE_GID_DEFAULT_MODE_SET) { if (mode == IB_CACHE_GID_DEFAULT_MODE_SET) {
mask = GID_ATTR_FIND_MASK_GID_TYPE | make_default_gid(ndev, &gid);
GID_ATTR_FIND_MASK_DEFAULT;
__ib_cache_gid_add(ib_dev, port, &gid, __ib_cache_gid_add(ib_dev, port, &gid,
&gid_attr, mask, true); &gid_attr, mask, true);
} else if (mode == IB_CACHE_GID_DEFAULT_MODE_DELETE) { } 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);
} }
} }
} }
......
...@@ -255,6 +255,7 @@ static void bond_delete_netdev_default_gids(struct ib_device *ib_dev, ...@@ -255,6 +255,7 @@ static void bond_delete_netdev_default_gids(struct ib_device *ib_dev,
struct net_device *rdma_ndev) struct net_device *rdma_ndev)
{ {
struct net_device *real_dev = rdma_vlan_dev_real_dev(event_ndev); struct net_device *real_dev = rdma_vlan_dev_real_dev(event_ndev);
unsigned long gid_type_mask;
if (!rdma_ndev) if (!rdma_ndev)
return; return;
...@@ -264,21 +265,22 @@ static void bond_delete_netdev_default_gids(struct ib_device *ib_dev, ...@@ -264,21 +265,22 @@ static void bond_delete_netdev_default_gids(struct ib_device *ib_dev,
rcu_read_lock(); rcu_read_lock();
if (rdma_is_upper_dev_rcu(rdma_ndev, event_ndev) && if (((rdma_ndev != event_ndev &&
is_eth_active_slave_of_bonding_rcu(rdma_ndev, real_dev) == !rdma_is_upper_dev_rcu(rdma_ndev, event_ndev)) ||
BONDING_SLAVE_STATE_INACTIVE) { is_eth_active_slave_of_bonding_rcu(rdma_ndev, real_dev)
unsigned long gid_type_mask; ==
BONDING_SLAVE_STATE_INACTIVE)) {
rcu_read_unlock(); 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 = roce_gid_type_mask_support(ib_dev, port);
gid_type_mask,
IB_CACHE_GID_DEFAULT_MODE_DELETE); ib_cache_gid_set_default_gid(ib_dev, port, rdma_ndev,
} else { gid_type_mask,
rcu_read_unlock(); IB_CACHE_GID_DEFAULT_MODE_DELETE);
}
} }
static void enum_netdev_ipv4_ips(struct ib_device *ib_dev, static void enum_netdev_ipv4_ips(struct ib_device *ib_dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment