Skip to contentSkip to conversation

Support RDMA events monitoring through

PATCH Superseded Michael Guralnik 2 participants 10 messages Aug 21, 2024

Subsystems (4)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover Support RDMA events monitoring through

This series consists of multiple parts that collectively offer a method to monitor RDMA events from userspace.
Using netlink, users will be able to monitor their IB device events and changes such as device register, device unregister and netdev attachment.

The first 2 patches contain fixes in mlx5 lag code that are required for accurate event reporting in case of a lag bond.

Patch #3 initializes phys_port_cnt early in device probe to allow the IB-to-netdev mapping API to work properly.

Patches #4,#5 modify and export IB-to-netdev mapping API, making it accessible to all vendors who wish to rely on it for associating their IB device with a netdevice.

Patches #6,#7 add the netlink support for reporting IB device events to userspace.

Chiara Meiohas (4):
RDMA/mlx5: Initialize phys_port_cnt earlier in RDMA device creation RDMA/mlx5: Use IB set_netdev and get_netdev functions RDMA/nldev: Add support for RDMA monitoring
RDMA/nldev: Expose whether RDMA monitoring is supported

Maher Sanalla (1):
RDMA/device: Clear netdev mapping in ib_device_get_netdev on
unregistration

Mark Bloch (2):
RDMA/mlx5: Check RoCE LAG status before getting netdev RDMA/mlx5: Obtain upper net device only when needed

 drivers/infiniband/core/device.c              |  43 ++++
 drivers/infiniband/core/netlink.c             |   1 +
 drivers/infiniband/core/nldev.c               | 123 +++++++++++
 drivers/infiniband/hw/mlx5/ib_rep.c           |  22 +-
 drivers/infiniband/hw/mlx5/main.c             | 197 +++++++++++++-----
 drivers/infiniband/hw/mlx5/mlx5_ib.h          |   3 +-
 .../net/ethernet/mellanox/mlx5/core/lag/lag.c |  76 +++----
 include/linux/mlx5/device.h                   |   1 +
 include/linux/mlx5/driver.h                   |   2 +-
 include/rdma/ib_verbs.h                       |   2 +
 include/rdma/rdma_netlink.h                   |  10 +
 include/uapi/rdma/rdma_netlink.h              |  16 ++
 12 files changed, 391 insertions(+), 105 deletions(-)
Signature · 1 line
2.17.2
#1 lore raw

PATCH 1/7 RDMA/mlx5: Check RoCE LAG status before getting netdev

From: Mark Bloch <[email protected]>

Check if RoCE LAG is active before calling the LAG layer for netdev. This clarifies if LAG is active. No behavior changes with this patch.

---
 drivers/infiniband/hw/mlx5/main.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)
drivers/infiniband/hw/mlx5/main.c +13 -6
index b85ad3c0bfa1..cdf1ce0f6b34 100644
@@ -198,12 +198,18 @@ static int mlx5_netdev_event(struct notifier_block *this,
 	case NETDEV_CHANGE:
 	case NETDEV_UP:
 	case NETDEV_DOWN: {
-		struct net_device *lag_ndev = mlx5_lag_get_roce_netdev(mdev);
 		struct net_device *upper = NULL;
 
-		if (lag_ndev) {
-			upper = netdev_master_upper_dev_get(lag_ndev);
-			dev_put(lag_ndev);
+		if (mlx5_lag_is_roce(mdev)) {
+			struct net_device *lag_ndev;
+
+			lag_ndev = mlx5_lag_get_roce_netdev(mdev);
+			if (lag_ndev) {
+				upper = netdev_master_upper_dev_get(lag_ndev);
+				dev_put(lag_ndev);
+			} else {
+				goto done;
+			}
 		}
 
 		if (ibdev->is_rep)
@@ -257,9 +263,10 @@ static struct net_device *mlx5_ib_get_netdev(struct ib_device *device,
 	if (!mdev)
 		return NULL;
 
-	ndev = mlx5_lag_get_roce_netdev(mdev);
-	if (ndev)
+	if (mlx5_lag_is_roce(mdev)) {
+		ndev = mlx5_lag_get_roce_netdev(mdev);
 		goto out;
+	}
 
 	/* Ensure ndev does not disappear before we invoke dev_hold()
 	 */
Signature · 1 line
2.17.2
#2 lore raw

PATCH 2/7 RDMA/mlx5: Obtain upper net device only when needed

In reply to Michael Guralnik

From: Mark Bloch <[email protected]>

Report the upper device's state as the RDMA port state only in RoCE LAG or switchdev LAG.

Fixes 27f9e0ccb6da ("net/mlx5: Lag, Add single RDMA device in multiport mode")
---
 drivers/infiniband/hw/mlx5/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/main.c +1 -1
index cdf1ce0f6b34..c75cc3d14e74 100644
@@ -558,7 +558,7 @@ static int mlx5_query_port_roce(struct ib_device *device, u32 port_num,
 	if (!ndev)
 		goto out;
 
-	if (dev->lag_active) {
+	if (mlx5_lag_is_roce(mdev) || mlx5_lag_is_sriov(mdev)) {
 		rcu_read_lock();
 		upper = netdev_master_upper_dev_get_rcu(ndev);
 		if (upper) {
Signature · 1 line
2.17.2
#3 lore raw

PATCH 3/7 RDMA/mlx5: Initialize phys_port_cnt earlier in RDMA device creation

In reply to Michael Guralnik

From: Chiara Meiohas <[email protected]>

phys_port_cnt of the IB device must be initialized before calling ib_device_set_netdev().

Previously, phys_port_cnt was initialized in the mlx5_ib init function. Remove this initialization to allow setting it separately, providing the flexibility to call ib_device_set_netdev before registering the IB device.

---
 drivers/infiniband/hw/mlx5/ib_rep.c | 1 +
 drivers/infiniband/hw/mlx5/main.c   | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/ib_rep.c +1 -0
index c7a4ee896121..1ad934685d80 100644
@@ -104,6 +104,7 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
 	ibdev->is_rep = true;
 	vport_index = rep->vport_index;
 	ibdev->port[vport_index].rep = rep;
+	ibdev->ib_dev.phys_port_cnt = num_ports;
 	ibdev->port[vport_index].roce.netdev =
 		mlx5_ib_get_rep_netdev(lag_master->priv.eswitch, rep->vport);
 	ibdev->mdev = lag_master;
drivers/infiniband/hw/mlx5/main.c +2 -1
index c75cc3d14e74..1046c92212c7 100644
@@ -3932,7 +3932,6 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
 
 	dev->ib_dev.node_type = RDMA_NODE_IB_CA;
 	dev->ib_dev.local_dma_lkey = 0 /* not supported for now */;
-	dev->ib_dev.phys_port_cnt = dev->num_ports;
 	dev->ib_dev.dev.parent = mdev->device;
 	dev->ib_dev.lag_flags = RDMA_LAG_FLAGS_HASH_ALL_SLAVES;
 
@@ -4647,6 +4646,7 @@ static struct ib_device *mlx5_ib_add_sub_dev(struct ib_device *parent,
 	mplane->mdev = mparent->mdev;
 	mplane->num_ports = mparent->num_plane;
 	mplane->sub_dev_name = name;
+	mplane->ib_dev.phys_port_cnt = mplane->num_ports;
 
 	ret = __mlx5_ib_add(mplane, &plane_profile);
 	if (ret)
@@ -4763,6 +4763,7 @@ static int mlx5r_probe(struct auxiliary_device *adev,
 
 	dev->mdev = mdev;
 	dev->num_ports = num_ports;
+	dev->ib_dev.phys_port_cnt = num_ports;
 
 	if (ll == IB_LINK_LAYER_ETHERNET && !mlx5_get_roce_state(mdev))
 		profile = &raw_eth_profile;
Signature · 1 line
2.17.2
#4 lore raw

PATCH 4/7 RDMA/device: Clear netdev mapping in ib_device_get_netdev on unregistration

In reply to Michael Guralnik

From: Maher Sanalla <[email protected]>

The caller of ib_device_get_netdev() relies on its result to accurately match a given netdev with the ib device associated netdev.

ib_device_get_netdev returns NULL when the IB device associated netdev is unregistering, preventing the caller of matching netdevs properly.

Thus, revise ib_device_get_netdev to assign NULL to netdev when the netdev is undergoing unregistration, allowing matching by the caller.

This change ensures proper netdev matching and reference count handling by the caller of ib_device_get_netdev/ib_device_set_netdev API.

Fixes c2261dd76b54 ("RDMA/device: Add ib_device_set_netdev() as an alternative to get_netdev"
---
 drivers/infiniband/core/device.c | 1 +
 1 file changed, 1 insertion(+)
drivers/infiniband/core/device.c +1 -0
index 0290aca18d26..583047457de2 100644
@@ -2257,6 +2257,7 @@ struct net_device *ib_device_get_netdev(struct ib_device *ib_dev,
 	 * propagation of an unregistering netdev.
 	 */
 	if (res && res->reg_state != NETREG_REGISTERED) {
+		ib_device_set_netdev(ib_dev, NULL, port);
 		dev_put(res);
 		return NULL;
 	}
Signature · 1 line
2.17.2
#5 lore raw

PATCH 5/7 RDMA/mlx5: Use IB set_netdev and get_netdev functions

In reply to Michael Guralnik

From: Chiara Meiohas <[email protected]>

The IB layer provides a common interface to store and get net devices associated to an IB device port (ib_device_set_netdev() and ib_device_get_netdev()).
Previously, mlx5_ib stored and managed the associated net devices internally.

Replace internal net device management in mlx5_ib with ib_device_set_netdev() when attaching/detaching a net device and ib_device_get_netdev() when retrieving the net device.

Export ib_device_get_netdev().

For mlx5 representors/PFs/VFs and lag creation we replace the netdev assignments with the IB set/get netdev functions.

In active-backup mode lag the active slave net device is stored in the lag itself. To assure the net device stored in a lag bond IB device is the active slave we implement the following:
- mlx5_core: when modifying the slave of a bond we send the internal driver event MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE.
- mlx5_ib: when catching the event call ib_device_set_netdev()

This patch also ensures the correct IB events are sent in switchdev lag.

While at it, when in multiport eswitch mode, only a single IB device is created for all ports. The said IB device will receive all netdev events of its VFs once loaded, thus to avoid overwriting the mapping of PF IB device to PF netdev, ignore NETDEV_REGISTER events if the ib device has already been mapped to a netdev.

---
 drivers/infiniband/core/device.c              |   4 +
 drivers/infiniband/hw/mlx5/ib_rep.c           |  23 +--
 drivers/infiniband/hw/mlx5/main.c             | 183 ++++++++++++------
 drivers/infiniband/hw/mlx5/mlx5_ib.h          |   3 +-
 .../net/ethernet/mellanox/mlx5/core/lag/lag.c |  76 ++++----
 include/linux/mlx5/device.h                   |   1 +
 include/linux/mlx5/driver.h                   |   2 +-
 include/rdma/ib_verbs.h                       |   2 +
 8 files changed, 191 insertions(+), 103 deletions(-)
drivers/infiniband/core/device.c +4 -0
index 583047457de2..b2fc5a13577c 100644
@@ -2236,6 +2236,9 @@ struct net_device *ib_device_get_netdev(struct ib_device *ib_dev,
 	if (!rdma_is_port_valid(ib_dev, port))
 		return NULL;
 
+	if (!ib_dev->port_data)
+		return NULL;
+
 	pdata = &ib_dev->port_data[port];
 
 	/*
@@ -2264,6 +2267,7 @@ struct net_device *ib_device_get_netdev(struct ib_device *ib_dev,
 
 	return res;
 }
+EXPORT_SYMBOL(ib_device_get_netdev);
 
 /**
  * ib_device_get_by_netdev - Find an IB device associated with a netdev
drivers/infiniband/hw/mlx5/ib_rep.c +12 -11
index 1ad934685d80..49af1cfbe6d1 100644
@@ -13,6 +13,7 @@ mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev,
 		      int vport_index)
 {
 	struct mlx5_ib_dev *ibdev;
+	struct net_device *ndev;
 
 	ibdev = mlx5_eswitch_uplink_get_proto_dev(dev->priv.eswitch, REP_IB);
 	if (!ibdev)
@@ -20,12 +21,9 @@ mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev,
 
 	ibdev->port[vport_index].rep = rep;
 	rep->rep_data[REP_IB].priv = ibdev;
-	write_lock(&ibdev->port[vport_index].roce.netdev_lock);
-	ibdev->port[vport_index].roce.netdev =
-		mlx5_ib_get_rep_netdev(rep->esw, rep->vport);
-	write_unlock(&ibdev->port[vport_index].roce.netdev_lock);
+	ndev = mlx5_ib_get_rep_netdev(rep->esw, rep->vport);
 
-	return 0;
+	return ib_device_set_netdev(&ibdev->ib_dev, ndev, vport_index + 1);
 }
 
 static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev);
@@ -104,11 +102,15 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
 	ibdev->is_rep = true;
 	vport_index = rep->vport_index;
 	ibdev->port[vport_index].rep = rep;
-	ibdev->ib_dev.phys_port_cnt = num_ports;
-	ibdev->port[vport_index].roce.netdev =
-		mlx5_ib_get_rep_netdev(lag_master->priv.eswitch, rep->vport);
 	ibdev->mdev = lag_master;
 	ibdev->num_ports = num_ports;
+	ibdev->ib_dev.phys_port_cnt = num_ports;
+	ret = ib_device_set_netdev(&ibdev->ib_dev,
+			mlx5_ib_get_rep_netdev(lag_master->priv.eswitch,
+					       rep->vport),
+			vport_index + 1);
+	if (ret)
+		goto fail_add;
 
 	ret = __mlx5_ib_add(ibdev, profile);
 	if (ret)
@@ -161,9 +163,8 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
 	}
 
 	port = &dev->port[vport_index];
-	write_lock(&port->roce.netdev_lock);
-	port->roce.netdev = NULL;
-	write_unlock(&port->roce.netdev_lock);
+
+	ib_device_set_netdev(&dev->ib_dev, NULL, vport_index + 1);
 	rep->rep_data[REP_IB].priv = NULL;
 	port->rep = NULL;
 
drivers/infiniband/hw/mlx5/main.c +129 -54

283 lines not on this page · raw message

drivers/infiniband/hw/mlx5/mlx5_ib.h +1 -2
index be83a4d91a34..fd06d0d27a72 100644
@@ -896,8 +896,6 @@ struct mlx5_roce {
 	/* Protect mlx5_ib_get_netdev from invoking dev_hold() with a NULL
 	 * netdev pointer
 	 */
-	rwlock_t		netdev_lock;
-	struct net_device	*netdev;
 	struct notifier_block	nb;
 	struct netdev_net_notifier nn;
 	struct notifier_block	mdev_nb;
@@ -1146,6 +1144,7 @@ struct mlx5_ib_dev {
 	/* protect accessing data_direct_dev */
 	struct mutex			data_direct_lock;
 	struct notifier_block		mdev_events;
+	struct notifier_block           lag_events;
 	int				num_ports;
 	/* serialize update of capability mask
 	 */
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +41 -35

100 lines not on this page · raw message

include/linux/mlx5/device.h +1 -0
index ba875a619b97..a38a17f8c12c 100644
@@ -370,6 +370,7 @@ enum mlx5_driver_event {
 	MLX5_DRIVER_EVENT_SF_PEER_DEVLINK,
 	MLX5_DRIVER_EVENT_AFFILIATION_DONE,
 	MLX5_DRIVER_EVENT_AFFILIATION_REMOVED,
+	MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE,
 };
 
 enum {
include/linux/mlx5/driver.h +1 -1
index a96438ded15f..46a7a3d11048 100644
@@ -643,6 +643,7 @@ struct mlx5_priv {
 	struct mlx5_sf_hw_table *sf_hw_table;
 	struct mlx5_sf_table *sf_table;
 #endif
+	struct blocking_notifier_head lag_nh;
 };
 
 enum mlx5_device_state {
@@ -1181,7 +1182,6 @@ bool mlx5_lag_mode_is_hash(struct mlx5_core_dev *dev);
 bool mlx5_lag_is_master(struct mlx5_core_dev *dev);
 bool mlx5_lag_is_shared_fdb(struct mlx5_core_dev *dev);
 bool mlx5_lag_is_mpesw(struct mlx5_core_dev *dev);
-struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev);
 u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev,
 			   struct net_device *slave);
 int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
include/rdma/ib_verbs.h +2 -0
index a1dcf812d787..aa8ede439905 100644
@@ -4453,6 +4453,8 @@ struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u32 port,
 					    const struct sockaddr *addr);
 int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev,
 			 unsigned int port);
+struct net_device *ib_device_get_netdev(struct ib_device *ib_dev,
+					u32 port);
 struct ib_wq *ib_create_wq(struct ib_pd *pd,
 			   struct ib_wq_init_attr *init_attr);
 int ib_destroy_wq_user(struct ib_wq *wq, struct ib_udata *udata);
Signature · 1 line
2.17.2
#6 lore raw

PATCH 6/7 RDMA/nldev: Add support for RDMA monitoring

In reply to Michael Guralnik

From: Chiara Meiohas <[email protected]>

Introduce a new netlink command to allow rdma event monitoring. The rdma events supported now are IB device registration/unregistration and net device attachment/detachment.

Example output of rdma monitor and the commands which trigger the events:

$ rdma monitor
$ rmmod mlx5_ib
[UNREGISTER]    dev 3
[UNREGISTER]    dev 0

$modprobe mlx5_ib
[REGISTER] dev 4
[NETDEV_ATTACH] dev 4 port 1 netdev 4
[REGISTER] dev 5
[NETDEV_ATTACH] dev 5 port 1 netdev 5

$ devlink dev eswitch set pci/0000:08:00.0 mode switchdev
[UNREGISTER]    dev 4
[REGISTER]      dev 6
[NETDEV_ATTACH] dev 6 port 6 netdev 4
$ echo 4 > /sys/class/net/eth2/device/sriov_numvfs
[NETDEV_ATTACH] dev 6 port 2 netdev 7
[NETDEV_ATTACH] dev 6 port 3 netdev 8
[NETDEV_ATTACH] dev 6 port 4 netdev 9
[NETDEV_ATTACH] dev 6 port 5 netdev 10
[REGISTER]      dev 7
[NETDEV_ATTACH] dev 7 port 1 netdev 11
[REGISTER]      dev 8
[NETDEV_ATTACH] dev 8 port 1 netdev 12
[REGISTER]      dev 9
[NETDEV_ATTACH] dev 9 port 1 netdev 13
[REGISTER]      dev 10
[NETDEV_ATTACH] dev 10 port 1 netdev 14
$ echo 0 > /sys/class/net/eth2/device/sriov_numvfs
[UNREGISTER]    dev 7
[UNREGISTER]    dev 8
[UNREGISTER]    dev 9
[UNREGISTER]    dev 10
[NETDEV_DETACH] dev 6 port 2
[NETDEV_DETACH] dev 6 port 3
[NETDEV_DETACH] dev 6 port 4
[NETDEV_DETACH] dev 6 port 5
---
 drivers/infiniband/core/device.c  |  38 ++++++++++
 drivers/infiniband/core/netlink.c |   1 +
 drivers/infiniband/core/nldev.c   | 117 ++++++++++++++++++++++++++++++
 include/rdma/rdma_netlink.h       |  10 +++
 include/uapi/rdma/rdma_netlink.h  |  15 ++++
 5 files changed, 181 insertions(+)
drivers/infiniband/core/device.c +38 -0
index b2fc5a13577c..2113eb7c7573 100644
@@ -1351,6 +1351,30 @@ static void prevent_dealloc_device(struct ib_device *ib_dev)
 {
 }
 
+static void ib_device_notify_register(struct ib_device *device)
+{
+	struct net_device *netdev;
+	u32 port;
+	int ret;
+
+	ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT);
+	if (ret)
+		return;
+
+	rdma_for_each_port(device, port) {
+		netdev = ib_device_get_netdev(device, port);
+		if (!netdev)
+			continue;
+
+		ret = rdma_nl_notify_event(device, port,
+					   RDMA_NETDEV_ATTACH_EVENT);
+		dev_put(netdev);
+		if (ret)
+			return;
+	}
+	return;
+}
+
 /**
  * ib_register_device - Register an IB device with IB core
  * @device: Device to register
@@ -1449,6 +1473,8 @@ int ib_register_device(struct ib_device *device, const char *name,
 	dev_set_uevent_suppress(&device->dev, false);
 	/* Mark for userspace that device is ready */
 	kobject_uevent(&device->dev.kobj, KOBJ_ADD);
+
+	ib_device_notify_register(device);
 	ib_device_put(device);
 
 	return 0;
@@ -1491,6 +1517,7 @@ static void __ib_unregister_device(struct ib_device *ib_dev)
 		goto out;
 
 	disable_device(ib_dev);
+	rdma_nl_notify_event(ib_dev, 0, RDMA_UNREGISTER_EVENT);
 
 	/* Expedite removing unregistered pointers from the hash table */
 	free_netdevs(ib_dev);
@@ -2159,6 +2186,7 @@ static void add_ndev_hash(struct ib_port_data *pdata)
 int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev,
 			 u32 port)
 {
+	enum rdma_nl_notify_event_type etype;
 	struct net_device *old_ndev;
 	struct ib_port_data *pdata;
 	unsigned long flags;
@@ -2190,6 +2218,16 @@ int ib_device_set_netdev(struct ib_device *ib_dev, struct net_device *ndev,
 	spin_unlock_irqrestore(&pdata->netdev_lock, flags);
 
 	add_ndev_hash(pdata);
+
+	down_read(&devices_rwsem);
+	if (xa_get_mark(&devices, ib_dev->index, DEVICE_REGISTERED) &&
+	    xa_load(&devices, ib_dev->index) == ib_dev) {
+		etype = ndev ?
+			RDMA_NETDEV_ATTACH_EVENT : RDMA_NETDEV_DETACH_EVENT;
+		rdma_nl_notify_event(ib_dev, port, etype);
+	}
+	up_read(&devices_rwsem);
+
 	return 0;
 }
 EXPORT_SYMBOL(ib_device_set_netdev);
drivers/infiniband/core/netlink.c +1 -0
index ae2db0c70788..def14c54b648 100644
@@ -311,6 +311,7 @@ int rdma_nl_net_init(struct rdma_dev_net *rnet)
 	struct net *net = read_pnet(&rnet->net);
 	struct netlink_kernel_cfg cfg = {
 		.input	= rdma_nl_rcv,
+		.flags = NL_CFG_F_NONROOT_RECV,
 	};
 	struct sock *nls;
 
drivers/infiniband/core/nldev.c +117 -0

129 lines not on this page · raw message

include/rdma/rdma_netlink.h +10 -0
index c2a79aeee113..a5b47ca4cd66 100644
@@ -110,6 +110,16 @@ int rdma_nl_multicast(struct net *net, struct sk_buff *skb,
  */
 bool rdma_nl_chk_listeners(unsigned int group);
 
+/**
+ * Prepare and send an event message
+ * @ib: the IB device which triggered the event
+ * @port_num: the port number which triggered the event - 0 if unused
+ * @type: the event type
+ * Returns 0 on success or a negative error code
+ */
+int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
+			 enum rdma_nl_notify_event_type type);
+
 struct rdma_link_ops {
 	struct list_head list;
 	const char *type;
include/uapi/rdma/rdma_netlink.h +15 -0
index 2f37568f5556..5f9636d26050 100644
@@ -15,6 +15,7 @@ enum {
 enum {
 	RDMA_NL_GROUP_IWPM = 2,
 	RDMA_NL_GROUP_LS,
+	RDMA_NL_GROUP_NOTIFY,
 	RDMA_NL_NUM_GROUPS
 };
 
@@ -305,6 +306,8 @@ enum rdma_nldev_command {
 
 	RDMA_NLDEV_CMD_DELDEV,
 
+	RDMA_NLDEV_CMD_MONITOR,
+
 	RDMA_NLDEV_NUM_OPS
 };
 
@@ -574,6 +577,8 @@ enum rdma_nldev_attr {
 
 	RDMA_NLDEV_ATTR_NAME_ASSIGN_TYPE,	/* u8 */
 
+	RDMA_NLDEV_ATTR_EVENT_TYPE,		/* u8 */
+
 	/*
 	 * Always the end
 	 */
@@ -624,4 +629,14 @@ enum rdma_nl_name_assign_type {
 	RDMA_NAME_ASSIGN_TYPE_USER = 1, /* Provided by user-space */
 };
 
+/*
+ * Supported rdma monitoring event types.
+ */
+enum rdma_nl_notify_event_type {
+	RDMA_REGISTER_EVENT,
+	RDMA_UNREGISTER_EVENT,
+	RDMA_NETDEV_ATTACH_EVENT,
+	RDMA_NETDEV_DETACH_EVENT,
+};
+
 #endif /* _UAPI_RDMA_NETLINK_H */
Signature · 1 line
2.17.2
#7 lore raw

Re: [PATCH rdma-next 6/7] RDMA/nldev: Add support for RDMA monitoring

kernel test robot noticed the following build errors:

Hi Michael,

kernel test robot noticed the following build errors:

[auto build test ERROR on rdma/for-next]
[also build test ERROR on linus/master v6.11-rc4 next-20240821] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Michael-Guralnik/RDMA-mlx5-Check-RoCE-LAG-status-before-getting-netdev/20240821-131236
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git for-next
patch link:    https://lore.kernel.org/r/20240821051017.7730-7-michaelgur%40nvidia.com
patch subject: [PATCH rdma-next 6/7] RDMA/nldev: Add support for RDMA monitoring
config: i386-randconfig-003-20240821 (https://download.01.org/0day-ci/archive/20240822/[email protected]/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240822/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All error/warnings (new ones prefixed by >>):

In file included from drivers/infiniband/core/device.c:45:

>> include/rdma/rdma_netlink.h:120:33: warning: declaration of 'struct ib_device' will not be visible outside of this function [-Wvisibility]
     120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
         |                                 ^
>> drivers/infiniband/core/device.c:1360:29: error: incompatible pointer types passing 'struct ib_device *' to parameter of type 'struct ib_device *' [-Werror,-Wincompatible-pointer-types]
    1360 |         ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT);
         |                                    ^~~~~~
   include/rdma/rdma_netlink.h:120:44: note: passing argument to parameter 'ib' here
     120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
         |                                            ^
   drivers/infiniband/core/device.c:1369:30: error: incompatible pointer types passing 'struct ib_device *' to parameter of type 'struct ib_device *' [-Werror,-Wincompatible-pointer-types]
    1369 |                 ret = rdma_nl_notify_event(device, port,
         |                                            ^~~~~~
   include/rdma/rdma_netlink.h:120:44: note: passing argument to parameter 'ib' here
     120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
         |                                            ^
   drivers/infiniband/core/device.c:1520:23: error: incompatible pointer types passing 'struct ib_device *' to parameter of type 'struct ib_device *' [-Werror,-Wincompatible-pointer-types]
    1520 |         rdma_nl_notify_event(ib_dev, 0, RDMA_UNREGISTER_EVENT);
         |                              ^~~~~~
   include/rdma/rdma_netlink.h:120:44: note: passing argument to parameter 'ib' here
     120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
         |                                            ^
   drivers/infiniband/core/device.c:2227:24: error: incompatible pointer types passing 'struct ib_device *' to parameter of type 'struct ib_device *' [-Werror,-Wincompatible-pointer-types]
    2227 |                 rdma_nl_notify_event(ib_dev, port, etype);
         |                                      ^~~~~~

include/rdma/rdma_netlink.h:120:44: note: passing argument to parameter 'ib' here
120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
| ^
1 warning and 4 errors generated.
--
In file included from drivers/infiniband/core/iwpm_msg.c:34:
In file included from drivers/infiniband/core/iwpm_util.h:50:

>> include/rdma/rdma_netlink.h:120:33: warning: declaration of 'struct ib_device' will not be visible outside of this function [-Wvisibility]

120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
| ^
1 warning generated.

vim +1360 drivers/infiniband/core/device.c

1353
1354 static void ib_device_notify_register(struct ib_device *device)
1355 {
1356 struct net_device *netdev;
1357 u32 port;
1358 int ret;
1359

> 1360		ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT);

1361 if (ret)
1362 return;
1363
1364 rdma_for_each_port(device, port) {
1365 netdev = ib_device_get_netdev(device, port);
1366 if (!netdev)
1367 continue;
1368
1369 ret = rdma_nl_notify_event(device, port,
1370 RDMA_NETDEV_ATTACH_EVENT);
1371 dev_put(netdev);
1372 if (ret)
1373 return;
1374 }
1375 return;
1376 }
1377

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
#8 lore raw

Re: [PATCH rdma-next 6/7] RDMA/nldev: Add support for RDMA monitoring

In reply to Michael Guralnik
kernel test robot noticed the following build errors:

Hi Michael,

kernel test robot noticed the following build errors:

[auto build test ERROR on rdma/for-next]
[also build test ERROR on linus/master v6.11-rc4 next-20240821] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Michael-Guralnik/RDMA-mlx5-Check-RoCE-LAG-status-before-getting-netdev/20240821-131236
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git for-next
patch link:    https://lore.kernel.org/r/20240821051017.7730-7-michaelgur%40nvidia.com
patch subject: [PATCH rdma-next 6/7] RDMA/nldev: Add support for RDMA monitoring
config: loongarch-defconfig (https://download.01.org/0day-ci/archive/20240822/[email protected]/config)
compiler: loongarch64-linux-gcc (GCC) 14.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240822/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All error/warnings (new ones prefixed by >>):

In file included from drivers/infiniband/core/device.c:45:

>> include/rdma/rdma_netlink.h:120:33: warning: 'struct ib_device' declared inside parameter list will not be visible outside of this definition or declaration
     120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
         |                                 ^~~~~~~~~
   drivers/infiniband/core/device.c: In function 'ib_device_notify_register':
>> drivers/infiniband/core/device.c:1360:36: error: passing argument 1 of 'rdma_nl_notify_event' from incompatible pointer type [-Wincompatible-pointer-types]
    1360 |         ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT);
         |                                    ^~~~~~
         |                                    |
         |                                    struct ib_device *
   include/rdma/rdma_netlink.h:120:44: note: expected 'struct ib_device *' but argument is of type 'struct ib_device *'
     120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
         |                          ~~~~~~~~~~~~~~~~~~^~
   drivers/infiniband/core/device.c:1369:44: error: passing argument 1 of 'rdma_nl_notify_event' from incompatible pointer type [-Wincompatible-pointer-types]
    1369 |                 ret = rdma_nl_notify_event(device, port,
         |                                            ^~~~~~
         |                                            |
         |                                            struct ib_device *
   include/rdma/rdma_netlink.h:120:44: note: expected 'struct ib_device *' but argument is of type 'struct ib_device *'
     120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
         |                          ~~~~~~~~~~~~~~~~~~^~
   drivers/infiniband/core/device.c: In function '__ib_unregister_device':
   drivers/infiniband/core/device.c:1520:30: error: passing argument 1 of 'rdma_nl_notify_event' from incompatible pointer type [-Wincompatible-pointer-types]
    1520 |         rdma_nl_notify_event(ib_dev, 0, RDMA_UNREGISTER_EVENT);
         |                              ^~~~~~
         |                              |
         |                              struct ib_device *
   include/rdma/rdma_netlink.h:120:44: note: expected 'struct ib_device *' but argument is of type 'struct ib_device *'
     120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
         |                          ~~~~~~~~~~~~~~~~~~^~
   drivers/infiniband/core/device.c: In function 'ib_device_set_netdev':
   drivers/infiniband/core/device.c:2227:38: error: passing argument 1 of 'rdma_nl_notify_event' from incompatible pointer type [-Wincompatible-pointer-types]
    2227 |                 rdma_nl_notify_event(ib_dev, port, etype);
         |                                      ^~~~~~
         |                                      |
         |                                      struct ib_device *

include/rdma/rdma_netlink.h:120:44: note: expected 'struct ib_device *' but argument is of type 'struct ib_device *'
120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
| ~~~~~~~~~~~~~~~~~~^~
--
In file included from drivers/infiniband/core/netlink.c:41:

>> include/rdma/rdma_netlink.h:120:33: warning: 'struct ib_device' declared inside parameter list will not be visible outside of this definition or declaration

120 | int rdma_nl_notify_event(struct ib_device *ib, u32 port_num,
| ^~~~~~~~~

vim +/rdma_nl_notify_event +1360 drivers/infiniband/core/device.c

1353
1354 static void ib_device_notify_register(struct ib_device *device)
1355 {
1356 struct net_device *netdev;
1357 u32 port;
1358 int ret;
1359

> 1360		ret = rdma_nl_notify_event(device, 0, RDMA_REGISTER_EVENT);

1361 if (ret)
1362 return;
1363
1364 rdma_for_each_port(device, port) {
1365 netdev = ib_device_get_netdev(device, port);
1366 if (!netdev)
1367 continue;
1368
1369 ret = rdma_nl_notify_event(device, port,
1370 RDMA_NETDEV_ATTACH_EVENT);
1371 dev_put(netdev);
1372 if (ret)
1373 return;
1374 }
1375 return;
1376 }
1377

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
#9 lore raw

PATCH 7/7 RDMA/nldev: Expose whether RDMA monitoring is supported

In reply to Michael Guralnik

From: Chiara Meiohas <[email protected]>

Extend the "rdma sys" command to display whether RDMA monitoring is supported.

RDMA monitoring is not supported in mlx4 because it does not use the ib_device_set_netdev() API, which sends the RDMA events.

Example output for kernel where monitoring is supported:

$ rdma sys show
netns shared privileged-qkey off monitor on copy-on-fork on

Example output for kernel where monitoring is not supported:

$ rdma sys show
netns shared privileged-qkey off monitor off copy-on-fork on
---
 drivers/infiniband/core/nldev.c  | 6 ++++++
 include/uapi/rdma/rdma_netlink.h | 1 +
 2 files changed, 7 insertions(+)
drivers/infiniband/core/nldev.c +6 -0
index 5acbde242b97..f6eaf9c1fc05 100644
@@ -1952,6 +1952,12 @@ static int nldev_sys_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
 		nlmsg_free(msg);
 		return err;
 	}
+
+	err = nla_put_u8(msg, RDMA_NLDEV_SYS_ATTR_MONITOR_MODE, 1);
+	if (err) {
+		nlmsg_free(msg);
+		return err;
+	}
 	/*
 	 * Copy-on-fork is supported.
 	 * See commits:
include/uapi/rdma/rdma_netlink.h +1 -0
index 5f9636d26050..39be09c0ffbb 100644
@@ -579,6 +579,7 @@ enum rdma_nldev_attr {
 
 	RDMA_NLDEV_ATTR_EVENT_TYPE,		/* u8 */
 
+	RDMA_NLDEV_SYS_ATTR_MONITOR_MODE,	/* u8 */
 	/*
 	 * Always the end
 	 */
Signature · 1 line
2.17.2