All of lore.kernel.org
 help / color / mirror / Atom feed
From: Aurelien Aptel <aaptel@nvidia.com>
To: linux-nvme@lists.infradead.org, netdev@vger.kernel.org,
	sagi@grimberg.me, hch@lst.de, kbusch@kernel.org, axboe@fb.com,
	chaitanyak@nvidia.com, davem@davemloft.net, kuba@kernel.org
Cc: Aurelien Aptel <aaptel@nvidia.com>,
	aurelien.aptel@gmail.com, smalin@nvidia.com, malin1024@gmail.com,
	ogerlitz@nvidia.com, yorayz@nvidia.com, borisp@nvidia.com,
	galshalom@nvidia.com, mgurtovoy@nvidia.com, edumazet@google.com,
	pabeni@redhat.com, imagedong@tencent.com
Subject: [PATCH v15 02/20] netlink: add new family to manage ULP_DDP enablement and stats
Date: Tue, 12 Sep 2023 09:59:31 +0000	[thread overview]
Message-ID: <20230912095949.5474-3-aaptel@nvidia.com> (raw)
In-Reply-To: <20230912095949.5474-1-aaptel@nvidia.com>

Add a new netlink family to get/set ULP DDP capabilities on a network
device and to retrieve statistics.

The messages use the genetlink infrastructure and are specified in a
YAML file which was used to generate some of the files in this commit:

./tools/net/ynl/ynl-gen-c.py --mode kernel \
    --spec ./Documentation/netlink/specs/ulp_ddp.yaml --header \
    -o net/core/ulp_ddp_gen_nl.h
./tools/net/ynl/ynl-gen-c.py --mode kernel \
    --spec ./Documentation/netlink/specs/ulp_ddp.yaml --source \
    -o net/core/ulp_ddp_gen_nl.c
./tools/net/ynl/ynl-gen-c.py --mode uapi \
    --spec ./Documentation/netlink/specs/ulp_ddp.yaml --header \
    > include/uapi/linux/ulp_ddp_nl.h

Signed-off-by: Shai Malin <smalin@nvidia.com>
Signed-off-by: Aurelien Aptel <aaptel@nvidia.com>
---
 Documentation/netlink/specs/ulp_ddp.yaml | 183 +++++++++++
 include/uapi/linux/ulp_ddp_nl.h          |  59 ++++
 net/core/Makefile                        |   2 +-
 net/core/ulp_ddp_gen_nl.c                |  85 +++++
 net/core/ulp_ddp_gen_nl.h                |  32 ++
 net/core/ulp_ddp_nl.c                    | 388 +++++++++++++++++++++++
 6 files changed, 748 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/netlink/specs/ulp_ddp.yaml
 create mode 100644 include/uapi/linux/ulp_ddp_nl.h
 create mode 100644 net/core/ulp_ddp_gen_nl.c
 create mode 100644 net/core/ulp_ddp_gen_nl.h
 create mode 100644 net/core/ulp_ddp_nl.c

diff --git a/Documentation/netlink/specs/ulp_ddp.yaml b/Documentation/netlink/specs/ulp_ddp.yaml
new file mode 100644
index 000000000000..882aa4e52992
--- /dev/null
+++ b/Documentation/netlink/specs/ulp_ddp.yaml
@@ -0,0 +1,183 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+#
+# Author: Aurelien Aptel <aaptel@nvidia.com>
+#
+# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES.  All rights reserved.
+#
+
+name: ulp_ddp
+
+protocol: genetlink
+
+doc: Netlink protocol to manage ULP DPP on network devices.
+
+definitions:
+  -
+    type: enum
+    name: cap
+    entries:
+      - nvme-tcp
+      - nvme-tcp-ddgst-rx
+
+uapi-header: linux/ulp_ddp_nl.h
+
+attribute-sets:
+  -
+    name: stat
+    attributes:
+      -
+        name: ifindex
+        doc: interface index of the net device.
+        type: u32
+      -
+        name: pad
+        type: pad
+      -
+        name: rx-nvmeotcp-sk-add
+        doc: Sockets successfully configured for NVMeTCP offloading.
+        type: u64
+      -
+        name: rx-nvmeotcp-sk-add-fail
+        doc: Sockets failed to be configured for NVMeTCP offloading.
+        type: u64
+      -
+        name: rx-nvmeotcp-sk-del
+        doc: Sockets with NVMeTCP offloading configuration removed.
+        type: u64
+      -
+        name: rx-nvmeotcp-setup
+        doc: NVMe-TCP IOs successfully configured for Rx Direct Data Placement.
+        type: u64
+      -
+        name: rx-nvmeotcp-setup-fail
+        doc: NVMe-TCP IOs failed to be configured for Rx Direct Data Placement.
+        type: u64
+      -
+        name: rx-nvmeotcp-teardown
+        doc: NVMe-TCP IOs with Rx Direct Data Placement configuration removed.
+        type: u64
+      -
+        name: rx-nvmeotcp-drop
+        doc: Packets failed the NVMeTCP offload validation.
+        type: u64
+      -
+        name: rx-nvmeotcp-resync
+        doc: >
+          NVMe-TCP resync operations were processed due to Rx TCP packets
+          re-ordering.
+        type: u64
+      -
+        name: rx-nvmeotcp-packets
+        doc: TCP packets successfully processed by the NVMeTCP offload.
+        type: u64
+      -
+        name: rx-nvmeotcp-bytes
+        doc: Bytes were successfully processed by the NVMeTCP offload.
+        type: u64
+  -
+    name: dev
+    attributes:
+      -
+        name: ifindex
+        doc: interface index of the net device.
+        type: u32
+      -
+        name: hw
+        doc: bitmask of the capabilities supported by the device.
+        type: u64
+        enum: cap
+        enum-as-flags: true
+      -
+        name: active
+        doc: bitmask of the capabilities currently enabled on the device.
+        type: u64
+        enum: cap
+        enum-as-flags: true
+      -
+        name: wanted
+        doc: >
+          new active bit values of the capabilities we want to set on the
+          device.
+        type: u64
+        enum: cap
+        enum-as-flags: true
+      -
+        name: wanted_mask
+        doc: bitmask of the meaningful bits in the wanted field.
+        type: u64
+        enum: cap
+        enum-as-flags: true
+      -
+        name: pad
+        type: pad
+
+operations:
+  list:
+    -
+      name: get
+      doc: Get ULP DDP capabilities.
+      attribute-set: dev
+      do:
+        request:
+          attributes:
+            - ifindex
+        reply: &dev-all
+          attributes:
+            - ifindex
+            - hw
+            - active
+        pre: ulp_ddp_get_netdev
+        post: ulp_ddp_put_netdev
+      dump:
+        reply: *dev-all
+    -
+      name: stats
+      doc: Get ULP DDP stats.
+      attribute-set: stat
+      do:
+        request:
+          attributes:
+            - ifindex
+        reply: &stats-all
+          attributes:
+            - ifindex
+            - rx-nvmeotcp-sk-add
+            - rx-nvmeotcp-sk-add-fail
+            - rx-nvmeotcp-sk-del
+            - rx-nvmeotcp-setup
+            - rx-nvmeotcp-setup-fail
+            - rx-nvmeotcp-teardown
+            - rx-nvmeotcp-drop
+            - rx-nvmeotcp-resync
+            - rx-nvmeotcp-packets
+            - rx-nvmeotcp-bytes
+        pre: ulp_ddp_get_netdev
+        post: ulp_ddp_put_netdev
+      dump:
+        reply: *stats-all
+    -
+      name: set
+      doc: Set ULP DDP capabilities.
+      attribute-set: dev
+      do:
+        request:
+          attributes:
+            - ifindex
+            - wanted
+            - wanted_mask
+        reply:
+          attributes:
+            - ifindex
+            - hw
+            - active
+        pre: ulp_ddp_get_netdev
+        post: ulp_ddp_put_netdev
+    -
+      name: set-ntf
+      doc: Notification for change in ULP DDP capabilities.
+      notify: get
+
+mcast-groups:
+  list:
+    -
+      name: mgmt
diff --git a/include/uapi/linux/ulp_ddp_nl.h b/include/uapi/linux/ulp_ddp_nl.h
new file mode 100644
index 000000000000..fc63749c9251
--- /dev/null
+++ b/include/uapi/linux/ulp_ddp_nl.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/*	Documentation/netlink/specs/ulp_ddp.yaml */
+/* YNL-GEN uapi header */
+
+#ifndef _UAPI_LINUX_ULP_DDP_H
+#define _UAPI_LINUX_ULP_DDP_H
+
+#define ULP_DDP_FAMILY_NAME	"ulp_ddp"
+#define ULP_DDP_FAMILY_VERSION	1
+
+enum ulp_ddp_cap {
+	ULP_DDP_CAP_NVME_TCP,
+	ULP_DDP_CAP_NVME_TCP_DDGST_RX,
+};
+
+enum {
+	ULP_DDP_A_STAT_IFINDEX = 1,
+	ULP_DDP_A_STAT_PAD,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_SK_ADD,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_SK_ADD_FAIL,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_SK_DEL,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_SETUP,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_SETUP_FAIL,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_TEARDOWN,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_DROP,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_RESYNC,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_PACKETS,
+	ULP_DDP_A_STAT_RX_NVMEOTCP_BYTES,
+
+	__ULP_DDP_A_STAT_MAX,
+	ULP_DDP_A_STAT_MAX = (__ULP_DDP_A_STAT_MAX - 1)
+};
+
+enum {
+	ULP_DDP_A_DEV_IFINDEX = 1,
+	ULP_DDP_A_DEV_HW,
+	ULP_DDP_A_DEV_ACTIVE,
+	ULP_DDP_A_DEV_WANTED,
+	ULP_DDP_A_DEV_WANTED_MASK,
+	ULP_DDP_A_DEV_PAD,
+
+	__ULP_DDP_A_DEV_MAX,
+	ULP_DDP_A_DEV_MAX = (__ULP_DDP_A_DEV_MAX - 1)
+};
+
+enum {
+	ULP_DDP_CMD_GET = 1,
+	ULP_DDP_CMD_STATS,
+	ULP_DDP_CMD_SET,
+	ULP_DDP_CMD_SET_NTF,
+
+	__ULP_DDP_CMD_MAX,
+	ULP_DDP_CMD_MAX = (__ULP_DDP_CMD_MAX - 1)
+};
+
+#define ULP_DDP_MCGRP_MGMT	"mgmt"
+
+#endif /* _UAPI_LINUX_ULP_DDP_H */
diff --git a/net/core/Makefile b/net/core/Makefile
index 09da9ed3f9ff..35a882e7276d 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -18,7 +18,7 @@ obj-y		     += dev.o dev_addr_lists.o dst.o netevent.o \
 obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o
 
 obj-y += net-sysfs.o
-obj-$(CONFIG_ULP_DDP) += ulp_ddp.o
+obj-$(CONFIG_ULP_DDP) += ulp_ddp.o ulp_ddp_nl.o ulp_ddp_gen_nl.o
 obj-$(CONFIG_PAGE_POOL) += page_pool.o
 obj-$(CONFIG_PROC_FS) += net-procfs.o
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
diff --git a/net/core/ulp_ddp_gen_nl.c b/net/core/ulp_ddp_gen_nl.c
new file mode 100644
index 000000000000..505bdc69b215
--- /dev/null
+++ b/net/core/ulp_ddp_gen_nl.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+/* Do not edit directly, auto-generated from: */
+/*	Documentation/netlink/specs/ulp_ddp.yaml */
+/* YNL-GEN kernel source */
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include "ulp_ddp_gen_nl.h"
+
+#include <uapi/linux/ulp_ddp_nl.h>
+
+/* ULP_DDP_CMD_GET - do */
+static const struct nla_policy ulp_ddp_get_nl_policy[ULP_DDP_A_DEV_IFINDEX + 1] = {
+	[ULP_DDP_A_DEV_IFINDEX] = { .type = NLA_U32, },
+};
+
+/* ULP_DDP_CMD_STATS - do */
+static const struct nla_policy ulp_ddp_stats_nl_policy[ULP_DDP_A_STAT_IFINDEX + 1] = {
+	[ULP_DDP_A_STAT_IFINDEX] = { .type = NLA_U32, },
+};
+
+/* ULP_DDP_CMD_SET - do */
+static const struct nla_policy ulp_ddp_set_nl_policy[ULP_DDP_A_DEV_WANTED_MASK + 1] = {
+	[ULP_DDP_A_DEV_IFINDEX] = { .type = NLA_U32, },
+	[ULP_DDP_A_DEV_WANTED] = NLA_POLICY_MASK(NLA_U64, 0x3),
+	[ULP_DDP_A_DEV_WANTED_MASK] = NLA_POLICY_MASK(NLA_U64, 0x3),
+};
+
+/* Ops table for ulp_ddp */
+static const struct genl_split_ops ulp_ddp_nl_ops[] = {
+	{
+		.cmd		= ULP_DDP_CMD_GET,
+		.pre_doit	= ulp_ddp_get_netdev,
+		.doit		= ulp_ddp_nl_get_doit,
+		.post_doit	= ulp_ddp_put_netdev,
+		.policy		= ulp_ddp_get_nl_policy,
+		.maxattr	= ULP_DDP_A_DEV_IFINDEX,
+		.flags		= GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd	= ULP_DDP_CMD_GET,
+		.dumpit	= ulp_ddp_nl_get_dumpit,
+		.flags	= GENL_CMD_CAP_DUMP,
+	},
+	{
+		.cmd		= ULP_DDP_CMD_STATS,
+		.pre_doit	= ulp_ddp_get_netdev,
+		.doit		= ulp_ddp_nl_stats_doit,
+		.post_doit	= ulp_ddp_put_netdev,
+		.policy		= ulp_ddp_stats_nl_policy,
+		.maxattr	= ULP_DDP_A_STAT_IFINDEX,
+		.flags		= GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd	= ULP_DDP_CMD_STATS,
+		.dumpit	= ulp_ddp_nl_stats_dumpit,
+		.flags	= GENL_CMD_CAP_DUMP,
+	},
+	{
+		.cmd		= ULP_DDP_CMD_SET,
+		.pre_doit	= ulp_ddp_get_netdev,
+		.doit		= ulp_ddp_nl_set_doit,
+		.post_doit	= ulp_ddp_put_netdev,
+		.policy		= ulp_ddp_set_nl_policy,
+		.maxattr	= ULP_DDP_A_DEV_WANTED_MASK,
+		.flags		= GENL_CMD_CAP_DO,
+	},
+};
+
+static const struct genl_multicast_group ulp_ddp_nl_mcgrps[] = {
+	[ULP_DDP_NLGRP_MGMT] = { "mgmt", },
+};
+
+struct genl_family ulp_ddp_nl_family __ro_after_init = {
+	.name		= ULP_DDP_FAMILY_NAME,
+	.version	= ULP_DDP_FAMILY_VERSION,
+	.netnsok	= true,
+	.parallel_ops	= true,
+	.module		= THIS_MODULE,
+	.split_ops	= ulp_ddp_nl_ops,
+	.n_split_ops	= ARRAY_SIZE(ulp_ddp_nl_ops),
+	.mcgrps		= ulp_ddp_nl_mcgrps,
+	.n_mcgrps	= ARRAY_SIZE(ulp_ddp_nl_mcgrps),
+};
diff --git a/net/core/ulp_ddp_gen_nl.h b/net/core/ulp_ddp_gen_nl.h
new file mode 100644
index 000000000000..277fb9dbfdcd
--- /dev/null
+++ b/net/core/ulp_ddp_gen_nl.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/*	Documentation/netlink/specs/ulp_ddp.yaml */
+/* YNL-GEN kernel header */
+
+#ifndef _LINUX_ULP_DDP_GEN_H
+#define _LINUX_ULP_DDP_GEN_H
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include <uapi/linux/ulp_ddp_nl.h>
+
+int ulp_ddp_get_netdev(const struct genl_split_ops *ops, struct sk_buff *skb,
+		       struct genl_info *info);
+void
+ulp_ddp_put_netdev(const struct genl_split_ops *ops, struct sk_buff *skb,
+		   struct genl_info *info);
+
+int ulp_ddp_nl_get_doit(struct sk_buff *skb, struct genl_info *info);
+int ulp_ddp_nl_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
+int ulp_ddp_nl_stats_doit(struct sk_buff *skb, struct genl_info *info);
+int ulp_ddp_nl_stats_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
+int ulp_ddp_nl_set_doit(struct sk_buff *skb, struct genl_info *info);
+
+enum {
+	ULP_DDP_NLGRP_MGMT,
+};
+
+extern struct genl_family ulp_ddp_nl_family;
+
+#endif /* _LINUX_ULP_DDP_GEN_H */
diff --git a/net/core/ulp_ddp_nl.c b/net/core/ulp_ddp_nl.c
new file mode 100644
index 000000000000..55e5c51b6d88
--- /dev/null
+++ b/net/core/ulp_ddp_nl.c
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ulp_ddp.c
+ *    Author: Aurelien Aptel <aaptel@nvidia.com>
+ *    Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES.  All rights reserved.
+ */
+#include <net/ulp_ddp.h>
+#include "ulp_ddp_gen_nl.h"
+
+#define ULP_DDP_STATS_CNT (sizeof(struct netlink_ulp_ddp_stats) / sizeof(u64))
+
+struct reply_data {
+	struct net_device *dev;
+	netdevice_tracker tracker;
+	void *hdr;
+	u32 ifindex;
+	DECLARE_BITMAP(hw, ULP_DDP_C_COUNT);
+	DECLARE_BITMAP(active, ULP_DDP_C_COUNT);
+	struct netlink_ulp_ddp_stats stats;
+};
+
+static size_t reply_size(int cmd)
+{
+	size_t len = 0;
+
+	BUILD_BUG_ON(ULP_DDP_C_COUNT > 64);
+
+	/* ifindex */
+	len += nla_total_size(sizeof(u32));
+
+	switch (cmd) {
+	case ULP_DDP_CMD_GET:
+	case ULP_DDP_CMD_SET:
+	case ULP_DDP_CMD_SET_NTF:
+		/* hw */
+		len += nla_total_size_64bit(sizeof(u64));
+
+		/* active */
+		len += nla_total_size_64bit(sizeof(u64));
+		break;
+	case ULP_DDP_CMD_STATS:
+		/* stats */
+		len += nla_total_size_64bit(sizeof(u64)) * ULP_DDP_STATS_CNT;
+		break;
+	}
+
+	return len;
+}
+
+/* pre_doit */
+int ulp_ddp_get_netdev(const struct genl_split_ops *ops,
+		       struct sk_buff *skb, struct genl_info *info)
+{
+	struct reply_data *data;
+
+	if (GENL_REQ_ATTR_CHECK(info, ULP_DDP_A_DEV_IFINDEX))
+		return -EINVAL;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->ifindex = nla_get_u32(info->attrs[ULP_DDP_A_DEV_IFINDEX]);
+	data->dev = netdev_get_by_index(genl_info_net(info),
+					data->ifindex,
+					&data->tracker,
+					GFP_KERNEL);
+	if (!data->dev) {
+		kfree(data);
+		NL_SET_BAD_ATTR(info->extack,
+				info->attrs[ULP_DDP_A_DEV_IFINDEX]);
+		return -ENOENT;
+	}
+
+	info->user_ptr[0] = data;
+	return 0;
+}
+
+/* post_doit */
+void ulp_ddp_put_netdev(const struct genl_split_ops *ops, struct sk_buff *skb,
+			struct genl_info *info)
+{
+	struct reply_data *data = info->user_ptr[0];
+
+	if (data) {
+		if (data->dev)
+			netdev_put(data->dev, &data->tracker);
+		kfree(data);
+	}
+}
+
+static int prepare_data(struct reply_data *data, int cmd)
+{
+	const struct ulp_ddp_dev_ops *ops = data->dev->netdev_ops->ulp_ddp_ops;
+	struct ulp_ddp_netdev_caps *caps = &data->dev->ulp_ddp_caps;
+
+	if (!ops)
+		return -EOPNOTSUPP;
+
+	switch (cmd) {
+	case ULP_DDP_CMD_GET:
+	case ULP_DDP_CMD_SET:
+	case ULP_DDP_CMD_SET_NTF:
+		bitmap_copy(data->hw, caps->hw, ULP_DDP_C_COUNT);
+		bitmap_copy(data->active, caps->active, ULP_DDP_C_COUNT);
+		break;
+	case ULP_DDP_CMD_STATS:
+		ops->get_stats(data->dev, &data->stats);
+		break;
+	}
+
+	return 0;
+}
+
+static int fill_data(struct sk_buff *rsp, struct reply_data *data, int cmd,
+		     const struct genl_info *info)
+{
+	u64 *val = (u64 *)&data->stats;
+	int attr, i;
+
+	data->hdr = genlmsg_iput(rsp, info);
+	if (!data->hdr)
+		return -EMSGSIZE;
+
+	switch (cmd) {
+	case ULP_DDP_CMD_GET:
+	case ULP_DDP_CMD_SET:
+	case ULP_DDP_CMD_SET_NTF:
+		if (nla_put_u32(rsp, ULP_DDP_A_DEV_IFINDEX, data->ifindex) ||
+		    nla_put_u64_64bit(rsp, ULP_DDP_A_DEV_HW,
+				      data->hw[0], ULP_DDP_A_DEV_PAD) ||
+		    nla_put_u64_64bit(rsp, ULP_DDP_A_DEV_ACTIVE,
+				      data->active[0], ULP_DDP_A_DEV_PAD))
+			goto err_cancel_msg;
+		break;
+	case ULP_DDP_CMD_STATS:
+		if (nla_put_u32(rsp, ULP_DDP_A_STAT_IFINDEX, data->ifindex))
+			goto err_cancel_msg;
+
+		attr = ULP_DDP_A_STAT_PAD + 1;
+		for (i = 0; i < ULP_DDP_STATS_CNT; i++, attr++)
+			if (nla_put_u64_64bit(rsp, attr, val[i],
+					      ULP_DDP_A_STAT_PAD))
+				goto err_cancel_msg;
+	}
+	genlmsg_end(rsp, data->hdr);
+
+	return 0;
+
+err_cancel_msg:
+	genlmsg_cancel(rsp, data->hdr);
+
+	return -EMSGSIZE;
+}
+
+int ulp_ddp_nl_get_doit(struct sk_buff *req, struct genl_info *info)
+{
+	struct reply_data *data = info->user_ptr[0];
+	struct sk_buff *rsp;
+	int ret = 0;
+
+	ret = prepare_data(data, ULP_DDP_CMD_GET);
+	if (ret)
+		return ret;
+
+	rsp = genlmsg_new(reply_size(ULP_DDP_CMD_GET), GFP_KERNEL);
+	if (!rsp)
+		return -EMSGSIZE;
+
+	ret = fill_data(rsp, data, ULP_DDP_CMD_GET, info);
+	if (ret < 0)
+		goto err_rsp;
+
+	return genlmsg_reply(rsp, info);
+
+err_rsp:
+	nlmsg_free(rsp);
+	return ret;
+}
+
+static void ulp_ddp_nl_notify_dev(struct reply_data *data)
+{
+	struct genl_info info;
+	struct sk_buff *ntf;
+
+	if (!genl_has_listeners(&ulp_ddp_nl_family, dev_net(data->dev),
+				ULP_DDP_NLGRP_MGMT))
+		return;
+
+	genl_info_init_ntf(&info, &ulp_ddp_nl_family, ULP_DDP_CMD_SET_NTF);
+	ntf = genlmsg_new(reply_size(ULP_DDP_CMD_GET), GFP_KERNEL);
+	if (!ntf)
+		return;
+
+	if (fill_data(ntf, data, ULP_DDP_CMD_SET_NTF, &info)) {
+		nlmsg_free(ntf);
+		return;
+	}
+
+	genlmsg_multicast_netns(&ulp_ddp_nl_family, dev_net(data->dev), ntf,
+				0, ULP_DDP_NLGRP_MGMT, GFP_KERNEL);
+}
+
+static int apply_bits(struct reply_data *data,
+		      unsigned long *req_wanted,
+		      unsigned long *req_mask,
+		      struct netlink_ext_ack *extack)
+{
+	DECLARE_BITMAP(old_active, ULP_DDP_C_COUNT);
+	DECLARE_BITMAP(new_active, ULP_DDP_C_COUNT);
+	DECLARE_BITMAP(all_bits, ULP_DDP_C_COUNT);
+	DECLARE_BITMAP(tmp, ULP_DDP_C_COUNT);
+	const struct ulp_ddp_dev_ops *ops;
+	struct ulp_ddp_netdev_caps *caps;
+	int ret;
+
+	caps = &data->dev->ulp_ddp_caps;
+	ops = data->dev->netdev_ops->ulp_ddp_ops;
+
+	if (!ops)
+		return -EOPNOTSUPP;
+
+	/* if (req_mask & ~all_bits) */
+	bitmap_fill(all_bits, ULP_DDP_C_COUNT);
+	bitmap_andnot(tmp, req_mask, all_bits, ULP_DDP_C_COUNT);
+	if (!bitmap_empty(tmp, ULP_DDP_C_COUNT))
+		return -EINVAL;
+
+	/* new_active = (old_active & ~req_mask) | (wanted & req_mask)
+	 * new_active &= caps_hw
+	 */
+	bitmap_copy(old_active, caps->active, ULP_DDP_C_COUNT);
+	bitmap_and(req_wanted, req_wanted, req_mask, ULP_DDP_C_COUNT);
+	bitmap_andnot(new_active, old_active, req_mask, ULP_DDP_C_COUNT);
+	bitmap_or(new_active, new_active, req_wanted, ULP_DDP_C_COUNT);
+	bitmap_and(new_active, new_active, caps->hw, ULP_DDP_C_COUNT);
+	if (!bitmap_equal(old_active, new_active, ULP_DDP_C_COUNT)) {
+		ret = ops->set_caps(data->dev, new_active, extack);
+		if (ret < 0)
+			return ret;
+		bitmap_copy(new_active, caps->active, ULP_DDP_C_COUNT);
+	}
+
+	/* return 1 to notify */
+	return !bitmap_equal(old_active, new_active, ULP_DDP_C_COUNT);
+}
+
+int ulp_ddp_nl_set_doit(struct sk_buff *skb, struct genl_info *info)
+{
+	struct reply_data *data = info->user_ptr[0];
+	unsigned long wanted, wanted_mask;
+	struct sk_buff *rsp;
+	bool notify;
+	int ret;
+
+	if (GENL_REQ_ATTR_CHECK(info, ULP_DDP_A_DEV_WANTED) ||
+	    GENL_REQ_ATTR_CHECK(info, ULP_DDP_A_DEV_WANTED_MASK))
+		return -EINVAL;
+
+	rsp = genlmsg_new(reply_size(ULP_DDP_CMD_STATS), GFP_KERNEL);
+	if (!rsp)
+		return -EMSGSIZE;
+
+	wanted = nla_get_u64(info->attrs[ULP_DDP_A_DEV_WANTED]);
+	wanted_mask = nla_get_u64(info->attrs[ULP_DDP_A_DEV_WANTED_MASK]);
+
+	ret = apply_bits(data, &wanted, &wanted_mask, info->extack);
+	if (ret < 0)
+		goto err_rsp;
+
+	notify = !!ret;
+	ret = prepare_data(data, ULP_DDP_CMD_SET);
+	if (ret)
+		goto err_rsp;
+
+	ret = fill_data(rsp, data, ULP_DDP_CMD_SET, info);
+	if (ret < 0)
+		goto err_rsp;
+
+	ret = genlmsg_reply(rsp, info);
+	if (notify)
+		ulp_ddp_nl_notify_dev(data);
+
+	return ret;
+
+err_rsp:
+	nlmsg_free(rsp);
+
+	return ret;
+}
+
+int ulp_ddp_nl_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(skb->sk);
+	struct net_device *netdev;
+	struct reply_data data;
+	int err = 0;
+
+	rtnl_lock();
+	for_each_netdev_dump(net, netdev, cb->args[0]) {
+		memset(&data, 0, sizeof(data));
+		data.dev = netdev;
+		data.ifindex = netdev->ifindex;
+
+		err = prepare_data(&data, ULP_DDP_CMD_GET);
+		if (err)
+			continue;
+
+		err = fill_data(skb, &data, ULP_DDP_CMD_GET,
+				genl_info_dump(cb));
+		if (err < 0)
+			break;
+	}
+	rtnl_unlock();
+
+	if (err != -EMSGSIZE)
+		return err;
+
+	return skb->len;
+}
+
+int ulp_ddp_nl_stats_doit(struct sk_buff *skb, struct genl_info *info)
+{
+	struct reply_data *data = info->user_ptr[0];
+	struct sk_buff *rsp;
+	int ret = 0;
+
+	ret = prepare_data(data, ULP_DDP_CMD_STATS);
+	if (ret)
+		return ret;
+
+	rsp = genlmsg_new(reply_size(ULP_DDP_CMD_STATS), GFP_KERNEL);
+	if (!rsp)
+		return -EMSGSIZE;
+
+	ret = fill_data(rsp, data, ULP_DDP_CMD_STATS, info);
+	if (ret < 0)
+		goto err_rsp;
+
+	return genlmsg_reply(rsp, info);
+
+err_rsp:
+	nlmsg_free(rsp);
+	return ret;
+}
+
+int ulp_ddp_nl_stats_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct net *net = sock_net(skb->sk);
+	struct net_device *netdev;
+	struct reply_data data;
+	int err = 0;
+
+	rtnl_lock();
+	for_each_netdev_dump(net, netdev, cb->args[0]) {
+		memset(&data, 0, sizeof(data));
+		data.dev = netdev;
+		data.ifindex = netdev->ifindex;
+
+		err = prepare_data(&data, ULP_DDP_CMD_STATS);
+		if (err)
+			continue;
+
+		err = fill_data(skb, &data, ULP_DDP_CMD_STATS,
+				genl_info_dump(cb));
+		if (err < 0)
+			break;
+	}
+	rtnl_unlock();
+
+	if (err != -EMSGSIZE)
+		return err;
+
+	return skb->len;
+}
+
+static int __init ulp_ddp_init(void)
+{
+	int err;
+
+	err = genl_register_family(&ulp_ddp_nl_family);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+subsys_initcall(ulp_ddp_init);
-- 
2.34.1



  parent reply	other threads:[~2023-09-12 10:00 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-12  9:59 [PATCH v15 00/20] nvme-tcp receive offloads Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 01/20] net: Introduce direct data placement tcp offload Aurelien Aptel
2023-09-12 16:17   ` David Ahern
2023-09-21  7:43     ` Aurelien Aptel
2023-09-21 12:33       ` David Ahern
2023-09-21 13:02         ` Aurelien Aptel
2023-09-12  9:59 ` Aurelien Aptel [this message]
2023-09-12  9:59 ` [PATCH v15 03/20] iov_iter: skip copy if src == dst for direct data placement Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 04/20] net/tls,core: export get_netdev_for_sock Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 05/20] nvme-tcp: Add DDP offload control path Aurelien Aptel
2023-09-12 13:24   ` Sagi Grimberg
2023-09-13  9:10     ` Aurelien Aptel
2023-09-13 10:46       ` Sagi Grimberg
2023-09-18 12:53         ` Aurelien Aptel
2023-09-13 10:49   ` Sagi Grimberg
2023-09-18 18:30     ` Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 06/20] nvme-tcp: Add DDP data-path Aurelien Aptel
2023-09-13 10:51   ` Sagi Grimberg
2023-09-18 18:26     ` Aurelien Aptel
2023-09-19  7:04       ` Sagi Grimberg
2023-09-20  8:39         ` Aurelien Aptel
2023-09-20 10:11           ` Sagi Grimberg
2023-09-20 16:04             ` Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 07/20] nvme-tcp: RX DDGST offload Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 08/20] nvme-tcp: Deal with netdevice DOWN events Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 09/20] Documentation: add ULP DDP offload documentation Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 10/20] net/mlx5e: Rename from tls to transport static params Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 11/20] net/mlx5e: Refactor ico sq polling to get budget Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 12/20] net/mlx5: Add NVMEoTCP caps, HW bits, 128B CQE and enumerations Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 13/20] net/mlx5e: NVMEoTCP, offload initialization Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 14/20] net/mlx5e: TCP flow steering for nvme-tcp acceleration Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 15/20] net/mlx5e: NVMEoTCP, use KLM UMRs for buffer registration Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 16/20] net/mlx5e: NVMEoTCP, queue init/teardown Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 17/20] net/mlx5e: NVMEoTCP, ddp setup and resync Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 18/20] net/mlx5e: NVMEoTCP, async ddp invalidation Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 19/20] net/mlx5e: NVMEoTCP, data-path for DDP+DDGST offload Aurelien Aptel
2023-09-12  9:59 ` [PATCH v15 20/20] net/mlx5e: NVMEoTCP, statistics Aurelien Aptel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230912095949.5474-3-aaptel@nvidia.com \
    --to=aaptel@nvidia.com \
    --cc=aurelien.aptel@gmail.com \
    --cc=axboe@fb.com \
    --cc=borisp@nvidia.com \
    --cc=chaitanyak@nvidia.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=galshalom@nvidia.com \
    --cc=hch@lst.de \
    --cc=imagedong@tencent.com \
    --cc=kbusch@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=malin1024@gmail.com \
    --cc=mgurtovoy@nvidia.com \
    --cc=netdev@vger.kernel.org \
    --cc=ogerlitz@nvidia.com \
    --cc=pabeni@redhat.com \
    --cc=sagi@grimberg.me \
    --cc=smalin@nvidia.com \
    --cc=yorayz@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.