Commit 62ed78f3 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'devlink-introduce-notifications-filtering'

Jiri Pirko says:

====================
devlink: introduce notifications filtering

From: Jiri Pirko <jiri@nvidia.com>

Currently the user listening on a socket for devlink notifications
gets always all messages for all existing devlink instances and objects,
even if he is interested only in one of those. That may cause
unnecessary overhead on setups with thousands of instances present.

User is currently able to narrow down the devlink objects replies
to dump commands by specifying select attributes.

Allow similar approach for notifications providing user a new
notify-filter-set command to select attributes with values
the notification message has to match. In that case, it is delivered
to the socket.

Note that the filtering is done per-socket, so multiple users may
specify different selection of attributes with values.

This patchset initially introduces support for following attributes:
DEVLINK_ATTR_BUS_NAME
DEVLINK_ATTR_DEV_NAME
DEVLINK_ATTR_PORT_INDEX

Patches #1 - #4 are preparations in devlink code, patch #3 is
                an optimization done on the way.
Patches #5 - #7 are preparations in netlink and generic netlink code.
Patch #8 is the main one in this set implementing of
         the notify-filter-set command and the actual
         per-socket filtering.
Patch #9 extends the infrastructure allowing to filter according
         to a port index.

Example:
$ devlink mon port pci/0000:08:00.0/32768
[port,new] pci/0000:08:00.0/32768: type notset flavour pcisf controller 0 pfnum 0 sfnum 107 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached roce enable
[port,new] pci/0000:08:00.0/32768: type eth flavour pcisf controller 0 pfnum 0 sfnum 107 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached roce enable
[port,new] pci/0000:08:00.0/32768: type eth netdev eth3 flavour pcisf controller 0 pfnum 0 sfnum 107 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached roce enable
[port,new] pci/0000:08:00.0/32768: type eth netdev eth3 flavour pcisf controller 0 pfnum 0 sfnum 107 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached roce enable
[port,new] pci/0000:08:00.0/32768: type eth flavour pcisf controller 0 pfnum 0 sfnum 107 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached roce enable
[port,new] pci/0000:08:00.0/32768: type notset flavour pcisf controller 0 pfnum 0 sfnum 107 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached roce enable
[port,del] pci/0000:08:00.0/32768: type notset flavour pcisf controller 0 pfnum 0 sfnum 107 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached roce enable
====================

Link: https://lore.kernel.org/r/20231216123001.1293639-1-jiri@resnulli.us


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents f7dd48ea ded6f77c
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -2254,3 +2254,14 @@ operations:
            - bus-name
            - dev-name
            - selftests

    -
      name: notify-filter-set
      doc: Set notification messages socket filter.
      attribute-set: devlink
      do:
        request:
          attributes:
            - bus-name
            - dev-name
            - port-index
+2 −3
Original line number Diff line number Diff line
@@ -59,8 +59,7 @@ static int cn_already_initialized;
 * both, or if both are zero then the group is looked up and sent there.
 */
int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 __group,
	gfp_t gfp_mask,
	int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data),
			 gfp_t gfp_mask, netlink_filter_fn filter,
			 void *filter_data)
{
	struct cn_callback_entry *__cbq;
+1 −2
Original line number Diff line number Diff line
@@ -100,8 +100,7 @@ void cn_del_callback(const struct cb_id *id);
 */
int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid,
			 u32 group, gfp_t gfp_mask,
			 int (*filter)(struct sock *dsk, struct sk_buff *skb,
				       void *data),
			 netlink_filter_fn filter,
			 void *filter_data);

/**
+4 −2
Original line number Diff line number Diff line
@@ -228,10 +228,12 @@ bool netlink_strict_get_check(struct sk_buff *skb);
int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 portid, int nonblock);
int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 portid,
		      __u32 group, gfp_t allocation);

typedef int (*netlink_filter_fn)(struct sock *dsk, struct sk_buff *skb, void *data);

int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb,
			       __u32 portid, __u32 group, gfp_t allocation,
			       int (*filter)(struct sock *dsk,
					     struct sk_buff *skb, void *data),
			       netlink_filter_fn filter,
			       void *filter_data);
int netlink_set_err(struct sock *ssk, __u32 portid, __u32 group, int code);
int netlink_register_notifier(struct notifier_block *nb);
+42 −4
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@ struct genl_info;
 * @split_ops: the split do/dump form of operation definition
 * @n_split_ops: number of entries in @split_ops, not that with split do/dump
 *	ops the number of entries is not the same as number of commands
 * @sock_priv_size: the size of per-socket private memory
 * @sock_priv_init: the per-socket private memory initializer
 * @sock_priv_destroy: the per-socket private memory destructor
 *
 * Attribute policies (the combination of @policy and @maxattr fields)
 * can be attached at the family level or at the operation level.
@@ -84,11 +87,17 @@ struct genl_family {
	const struct genl_multicast_group *mcgrps;
	struct module		*module;

	size_t			sock_priv_size;
	void			(*sock_priv_init)(void *priv);
	void			(*sock_priv_destroy)(void *priv);

/* private: internal use only */
	/* protocol family identifier */
	int			id;
	/* starting number of multicast group IDs in this family */
	unsigned int		mcgrp_offset;
	/* list of per-socket privs */
	struct xarray		*sock_privs;
};

/**
@@ -298,6 +307,8 @@ static inline bool genl_info_is_ntf(const struct genl_info *info)
	return !info->nlhdr;
}

void *__genl_sk_priv_get(struct genl_family *family, struct sock *sk);
void *genl_sk_priv_get(struct genl_family *family, struct sock *sk);
int genl_register_family(struct genl_family *family);
int genl_unregister_family(const struct genl_family *family);
void genl_notify(const struct genl_family *family, struct sk_buff *skb,
@@ -438,22 +449,49 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
}

/**
 * genlmsg_multicast_netns - multicast a netlink message to a specific netns
 * genlmsg_multicast_netns_filtered - multicast a netlink message
 *				      to a specific netns with filter
 *				      function
 * @family: the generic netlink family
 * @net: the net namespace
 * @skb: netlink message as socket buffer
 * @portid: own netlink portid to avoid sending to yourself
 * @group: offset of multicast group in groups array
 * @flags: allocation flags
 * @filter: filter function
 * @filter_data: filter function private data
 *
 * Return: 0 on success, negative error code for failure.
 */
static inline int genlmsg_multicast_netns(const struct genl_family *family,
static inline int
genlmsg_multicast_netns_filtered(const struct genl_family *family,
				 struct net *net, struct sk_buff *skb,
					  u32 portid, unsigned int group, gfp_t flags)
				 u32 portid, unsigned int group, gfp_t flags,
				 netlink_filter_fn filter,
				 void *filter_data)
{
	if (WARN_ON_ONCE(group >= family->n_mcgrps))
		return -EINVAL;
	group = family->mcgrp_offset + group;
	return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
	return nlmsg_multicast_filtered(net->genl_sock, skb, portid, group,
					flags, filter, filter_data);
}

/**
 * genlmsg_multicast_netns - multicast a netlink message to a specific netns
 * @family: the generic netlink family
 * @net: the net namespace
 * @skb: netlink message as socket buffer
 * @portid: own netlink portid to avoid sending to yourself
 * @group: offset of multicast group in groups array
 * @flags: allocation flags
 */
static inline int genlmsg_multicast_netns(const struct genl_family *family,
					  struct net *net, struct sk_buff *skb,
					  u32 portid, unsigned int group, gfp_t flags)
{
	return genlmsg_multicast_netns_filtered(family, net, skb, portid,
						group, flags, NULL, NULL);
}

/**
Loading