netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support)
@ 2023-10-06  9:14 Amritha Nambiar
  2023-10-06  9:14 ` [net-next PATCH v4 01/10] netdev-genl: spec: Extend netdev netlink spec in YAML for queue Amritha Nambiar
                   ` (9 more replies)
  0 siblings, 10 replies; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:14 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Add the capability to export the following via netdev-genl interface:
- queue information supported by the device
- NAPI information supported by the device

Introduce support for associating  queue and NAPI instance.
Extend the netdev_genl generic netlink family for netdev
with queue and NAPI data. 

The queue parameters exposed are:
- queue index
- queue type
- ifindex
- NAPI id associated with the queue
- tx maxrate
Additional rx and tx queue parameters can be exposed in follow up
patches by stashing them in netdev queue structures.  XDP queue type
can also be supported in future.

The NAPI fields exposed are:
- NAPI id
- NAPI device ifindex
- Interrupt number associated with the NAPI instance
- PID for the NAPI thread

This series only supports 'get' ability for retrieving
certain queue and NAPI attributes. The 'set' ability for
configuring queue and associated NAPI instance via netdev-genl
will be submitted as a separate patch series.

Previous discussion at:
https://lore.kernel.org/netdev/c8476530638a5f4381d64db0e024ed49c2db3b02.camel@gmail.com/T/#m00999652a8b4731fbdb7bf698d2e3666c65a60e7

$ ./cli.py --spec netdev.yaml --do queue-get  --json='{"ifindex": 12, "queue-id": 0, "queue-type": 0}'
{'ifindex': 12, 'napi-id': 593, 'queue-id': 0, 'queue-type': 'rx'}

$ ./cli.py --spec netdev.yaml  --do queue-get --json='{"ifindex": 12, "queue-id": 0, "queue-type": 1}'
{'ifindex': 12, 'napi-id': 593, 'queue-id': 0, 'queue-type': 'tx', 'tx-maxrate': 0}

$ ./cli.py --spec netdev.yaml  --dump queue-get --json='{"ifindex": 12}'
[{'ifindex': 12, 'napi-id': 593, 'queue-id': 0, 'queue-type': 'rx'},
 {'ifindex': 12, 'napi-id': 594, 'queue-id': 1, 'queue-type': 'rx'},
 {'ifindex': 12, 'napi-id': 595, 'queue-id': 2, 'queue-type': 'rx'},
 {'ifindex': 12, 'napi-id': 596, 'queue-id': 3, 'queue-type': 'rx'},
 {'ifindex': 12, 'napi-id': 593, 'queue-id': 0, 'queue-type': 'tx', 'tx-maxrate': 0},
 {'ifindex': 12, 'napi-id': 594, 'queue-id': 1, 'queue-type': 'tx', 'tx-maxrate': 0},
 {'ifindex': 12, 'napi-id': 595, 'queue-id': 2, 'queue-type': 'tx', 'tx-maxrate': 0},
 {'ifindex': 12, 'napi-id': 596, 'queue-id': 3, 'queue-type': 'tx', 'tx-maxrate': 0}]

$ ./cli.py --spec netdev.yaml --do napi-get --json='{"napi-id": 593}'
{'ifindex': 12, 'irq': 291, 'napi-id': 593, 'pid': 3817}

$ ./cli.py --spec netdev.yaml --dump napi-get --json='{"ifindex": 12}'
[{'ifindex': 12, 'irq': 294, 'napi-id': 596, 'pid': 3814},
 {'ifindex': 12, 'irq': 293, 'napi-id': 595, 'pid': 3815},
 {'ifindex': 12, 'irq': 292, 'napi-id': 594, 'pid': 3816},
 {'ifindex': 12, 'irq': 291, 'napi-id': 593, 'pid': 3817}]

v3 -> v4
Minor nits, changed function name, used list_for_each_entry in place
of _rcu

v2 -> v3
* Implemented queue as separate netlink object
with support for exposing per-queue paramters
* Removed queue-list associations with NAPI
* Addressed other review feedback WRT tracking list
iterations

v1 -> v2
* Removed multi-attr nest for NAPI object
* Added support for flat/individual NAPI objects
* Changed 'do' command to take napi-id as argument
* Supported filtered 'dump' (dump with ifindex for a netdev and dump for
  all netdevs)

RFC -> v1
* Changed to separate 'napi_get' command
* Added support to expose interrupt and PID for the NAPI
* Used list of netdev queue structs
* Split patches further and fixed code style and errors

---

Amritha Nambiar (10):
      netdev-genl: spec: Extend netdev netlink spec in YAML for queue
      net: Add queue and napi association
      ice: Add support in the driver for associating queue with napi
      netdev-genl: Add netlink framework functions for queue
      netdev-genl: spec: Extend netdev netlink spec in YAML for NAPI
      netdev-genl: Add netlink framework functions for napi
      netdev-genl: spec: Add irq in netdev netlink YAML spec
      net: Add NAPI IRQ support
      netdev-genl: spec: Add PID in netdev netlink YAML spec
      netdev-genl: Add PID for the NAPI thread


 Documentation/netlink/specs/netdev.yaml   |   92 ++++++++
 drivers/net/ethernet/intel/ice/ice_lib.c  |   62 +++++
 drivers/net/ethernet/intel/ice/ice_lib.h  |    4 
 drivers/net/ethernet/intel/ice/ice_main.c |    4 
 include/linux/netdevice.h                 |   13 +
 include/net/netdev_rx_queue.h             |    2 
 include/uapi/linux/netdev.h               |   28 ++
 net/core/dev.c                            |   39 +++
 net/core/netdev-genl-gen.c                |   50 ++++
 net/core/netdev-genl-gen.h                |    5 
 net/core/netdev-genl.c                    |  347 +++++++++++++++++++++++++++++
 tools/include/uapi/linux/netdev.h         |   28 ++
 tools/net/ynl/generated/netdev-user.c     |  295 +++++++++++++++++++++++++
 tools/net/ynl/generated/netdev-user.h     |  181 +++++++++++++++
 14 files changed, 1146 insertions(+), 4 deletions(-)

--

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 01/10] netdev-genl: spec: Extend netdev netlink spec in YAML for queue
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
@ 2023-10-06  9:14 ` Amritha Nambiar
  2023-10-11  2:12   ` Jakub Kicinski
  2023-10-06  9:14 ` [net-next PATCH v4 02/10] net: Add queue and napi association Amritha Nambiar
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:14 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Add support in netlink spec(netdev.yaml) for queue information.
Add code generated from the spec.

Note: The "queue-type" attribute currently takes values 0 and 1
for rx and tx queue type respectively. I haven't figured out the
ynl library changes to support string user input ("rx" and "tx")
to enum value conversion in the generated C code.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 Documentation/netlink/specs/netdev.yaml |   52 ++++++++++
 include/uapi/linux/netdev.h             |   17 +++
 net/core/netdev-genl-gen.c              |   26 +++++
 net/core/netdev-genl-gen.h              |    3 +
 net/core/netdev-genl.c                  |   10 ++
 tools/include/uapi/linux/netdev.h       |   17 +++
 tools/net/ynl/generated/netdev-user.c   |  159 +++++++++++++++++++++++++++++++
 tools/net/ynl/generated/netdev-user.h   |  102 ++++++++++++++++++++
 8 files changed, 386 insertions(+)

diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml
index 14511b13f305..4694acfe0e50 100644
--- a/Documentation/netlink/specs/netdev.yaml
+++ b/Documentation/netlink/specs/netdev.yaml
@@ -55,6 +55,10 @@ definitions:
         name: hash
         doc:
           Device is capable of exposing receive packet hash via bpf_xdp_metadata_rx_hash().
+  -
+    name: queue-type
+    type: enum
+    entries: [ rx, tx ]
 
 attribute-sets:
   -
@@ -87,6 +91,32 @@ attribute-sets:
         type: u64
         enum: xdp-rx-metadata
 
+  -
+    name: queue
+    attributes:
+      -
+        name: queue-id
+        doc: queue index
+        type: u32
+      -
+        name: ifindex
+        doc: netdev ifindex
+        type: u32
+        checks:
+          min: 1
+      -
+        name: queue-type
+        doc: queue type as rx, tx
+        type: u32
+        enum: queue-type
+      -
+        name: napi-id
+        doc: napi id
+        type: u32
+      -
+        name: tx-maxrate
+        type: u32
+
 operations:
   list:
     -
@@ -120,6 +150,28 @@ operations:
       doc: Notification about device configuration being changed.
       notify: dev-get
       mcgrp: mgmt
+    -
+      name: queue-get
+      doc: queue information
+      attribute-set: queue
+      do:
+        request:
+          attributes:
+            - ifindex
+            - queue-type
+            - queue-id
+        reply: &queue-get-op
+          attributes:
+            - queue-id
+            - queue-type
+            - napi-id
+            - ifindex
+            - tx-maxrate
+      dump:
+        request:
+          attributes:
+            - ifindex
+        reply: *queue-get-op
 
 mcast-groups:
   list:
diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h
index 2943a151d4f1..69f657a2020f 100644
--- a/include/uapi/linux/netdev.h
+++ b/include/uapi/linux/netdev.h
@@ -53,6 +53,11 @@ enum netdev_xdp_rx_metadata {
 	NETDEV_XDP_RX_METADATA_MASK = 3,
 };
 
+enum netdev_queue_type {
+	NETDEV_QUEUE_TYPE_RX,
+	NETDEV_QUEUE_TYPE_TX,
+};
+
 enum {
 	NETDEV_A_DEV_IFINDEX = 1,
 	NETDEV_A_DEV_PAD,
@@ -64,11 +69,23 @@ enum {
 	NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
 };
 
+enum {
+	NETDEV_A_QUEUE_QUEUE_ID = 1,
+	NETDEV_A_QUEUE_IFINDEX,
+	NETDEV_A_QUEUE_QUEUE_TYPE,
+	NETDEV_A_QUEUE_NAPI_ID,
+	NETDEV_A_QUEUE_TX_MAXRATE,
+
+	__NETDEV_A_QUEUE_MAX,
+	NETDEV_A_QUEUE_MAX = (__NETDEV_A_QUEUE_MAX - 1)
+};
+
 enum {
 	NETDEV_CMD_DEV_GET = 1,
 	NETDEV_CMD_DEV_ADD_NTF,
 	NETDEV_CMD_DEV_DEL_NTF,
 	NETDEV_CMD_DEV_CHANGE_NTF,
+	NETDEV_CMD_QUEUE_GET,
 
 	__NETDEV_CMD_MAX,
 	NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)
diff --git a/net/core/netdev-genl-gen.c b/net/core/netdev-genl-gen.c
index ea9231378aa6..85d556a051db 100644
--- a/net/core/netdev-genl-gen.c
+++ b/net/core/netdev-genl-gen.c
@@ -15,6 +15,18 @@ static const struct nla_policy netdev_dev_get_nl_policy[NETDEV_A_DEV_IFINDEX + 1
 	[NETDEV_A_DEV_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1),
 };
 
+/* NETDEV_CMD_QUEUE_GET - do */
+static const struct nla_policy netdev_queue_get_do_nl_policy[NETDEV_A_QUEUE_QUEUE_TYPE + 1] = {
+	[NETDEV_A_QUEUE_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1),
+	[NETDEV_A_QUEUE_QUEUE_TYPE] = NLA_POLICY_MAX(NLA_U32, 1),
+	[NETDEV_A_QUEUE_QUEUE_ID] = { .type = NLA_U32, },
+};
+
+/* NETDEV_CMD_QUEUE_GET - dump */
+static const struct nla_policy netdev_queue_get_dump_nl_policy[NETDEV_A_QUEUE_IFINDEX + 1] = {
+	[NETDEV_A_QUEUE_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1),
+};
+
 /* Ops table for netdev */
 static const struct genl_split_ops netdev_nl_ops[] = {
 	{
@@ -29,6 +41,20 @@ static const struct genl_split_ops netdev_nl_ops[] = {
 		.dumpit	= netdev_nl_dev_get_dumpit,
 		.flags	= GENL_CMD_CAP_DUMP,
 	},
+	{
+		.cmd		= NETDEV_CMD_QUEUE_GET,
+		.doit		= netdev_nl_queue_get_doit,
+		.policy		= netdev_queue_get_do_nl_policy,
+		.maxattr	= NETDEV_A_QUEUE_QUEUE_TYPE,
+		.flags		= GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd		= NETDEV_CMD_QUEUE_GET,
+		.dumpit		= netdev_nl_queue_get_dumpit,
+		.policy		= netdev_queue_get_dump_nl_policy,
+		.maxattr	= NETDEV_A_QUEUE_IFINDEX,
+		.flags		= GENL_CMD_CAP_DUMP,
+	},
 };
 
 static const struct genl_multicast_group netdev_nl_mcgrps[] = {
diff --git a/net/core/netdev-genl-gen.h b/net/core/netdev-genl-gen.h
index 7b370c073e7d..263c94f77bad 100644
--- a/net/core/netdev-genl-gen.h
+++ b/net/core/netdev-genl-gen.h
@@ -13,6 +13,9 @@
 
 int netdev_nl_dev_get_doit(struct sk_buff *skb, struct genl_info *info);
 int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
+int netdev_nl_queue_get_doit(struct sk_buff *skb, struct genl_info *info);
+int netdev_nl_queue_get_dumpit(struct sk_buff *skb,
+			       struct netlink_callback *cb);
 
 enum {
 	NETDEV_NLGRP_MGMT,
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index fe61f85bcf33..336c608e6a6b 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -129,6 +129,16 @@ int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+int netdev_nl_queue_get_doit(struct sk_buff *skb, struct genl_info *info)
+{
+	return -EOPNOTSUPP;
+}
+
+int netdev_nl_queue_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	return -EOPNOTSUPP;
+}
+
 static int netdev_genl_netdevice_event(struct notifier_block *nb,
 				       unsigned long event, void *ptr)
 {
diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h
index 2943a151d4f1..69f657a2020f 100644
--- a/tools/include/uapi/linux/netdev.h
+++ b/tools/include/uapi/linux/netdev.h
@@ -53,6 +53,11 @@ enum netdev_xdp_rx_metadata {
 	NETDEV_XDP_RX_METADATA_MASK = 3,
 };
 
+enum netdev_queue_type {
+	NETDEV_QUEUE_TYPE_RX,
+	NETDEV_QUEUE_TYPE_TX,
+};
+
 enum {
 	NETDEV_A_DEV_IFINDEX = 1,
 	NETDEV_A_DEV_PAD,
@@ -64,11 +69,23 @@ enum {
 	NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
 };
 
+enum {
+	NETDEV_A_QUEUE_QUEUE_ID = 1,
+	NETDEV_A_QUEUE_IFINDEX,
+	NETDEV_A_QUEUE_QUEUE_TYPE,
+	NETDEV_A_QUEUE_NAPI_ID,
+	NETDEV_A_QUEUE_TX_MAXRATE,
+
+	__NETDEV_A_QUEUE_MAX,
+	NETDEV_A_QUEUE_MAX = (__NETDEV_A_QUEUE_MAX - 1)
+};
+
 enum {
 	NETDEV_CMD_DEV_GET = 1,
 	NETDEV_CMD_DEV_ADD_NTF,
 	NETDEV_CMD_DEV_DEL_NTF,
 	NETDEV_CMD_DEV_CHANGE_NTF,
+	NETDEV_CMD_QUEUE_GET,
 
 	__NETDEV_CMD_MAX,
 	NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)
diff --git a/tools/net/ynl/generated/netdev-user.c b/tools/net/ynl/generated/netdev-user.c
index b5ffe8cd1144..b597bab2b85b 100644
--- a/tools/net/ynl/generated/netdev-user.c
+++ b/tools/net/ynl/generated/netdev-user.c
@@ -18,6 +18,7 @@ static const char * const netdev_op_strmap[] = {
 	[NETDEV_CMD_DEV_ADD_NTF] = "dev-add-ntf",
 	[NETDEV_CMD_DEV_DEL_NTF] = "dev-del-ntf",
 	[NETDEV_CMD_DEV_CHANGE_NTF] = "dev-change-ntf",
+	[NETDEV_CMD_QUEUE_GET] = "queue-get",
 };
 
 const char *netdev_op_str(int op)
@@ -58,6 +59,18 @@ const char *netdev_xdp_rx_metadata_str(enum netdev_xdp_rx_metadata value)
 	return netdev_xdp_rx_metadata_strmap[value];
 }
 
+static const char * const netdev_queue_type_strmap[] = {
+	[0] = "rx",
+	[1] = "tx",
+};
+
+const char *netdev_queue_type_str(enum netdev_queue_type value)
+{
+	if (value < 0 || value >= (int)MNL_ARRAY_SIZE(netdev_queue_type_strmap))
+		return NULL;
+	return netdev_queue_type_strmap[value];
+}
+
 /* Policies */
 struct ynl_policy_attr netdev_dev_policy[NETDEV_A_DEV_MAX + 1] = {
 	[NETDEV_A_DEV_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, },
@@ -72,6 +85,19 @@ struct ynl_policy_nest netdev_dev_nest = {
 	.table = netdev_dev_policy,
 };
 
+struct ynl_policy_attr netdev_queue_policy[NETDEV_A_QUEUE_MAX + 1] = {
+	[NETDEV_A_QUEUE_QUEUE_ID] = { .name = "queue-id", .type = YNL_PT_U32, },
+	[NETDEV_A_QUEUE_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, },
+	[NETDEV_A_QUEUE_QUEUE_TYPE] = { .name = "queue-type", .type = YNL_PT_U32, },
+	[NETDEV_A_QUEUE_NAPI_ID] = { .name = "napi-id", .type = YNL_PT_U32, },
+	[NETDEV_A_QUEUE_TX_MAXRATE] = { .name = "tx-maxrate", .type = YNL_PT_U32, },
+};
+
+struct ynl_policy_nest netdev_queue_nest = {
+	.max_attr = NETDEV_A_QUEUE_MAX,
+	.table = netdev_queue_policy,
+};
+
 /* Common nested types */
 /* ============== NETDEV_CMD_DEV_GET ============== */
 /* NETDEV_CMD_DEV_GET - do */
@@ -197,6 +223,139 @@ void netdev_dev_get_ntf_free(struct netdev_dev_get_ntf *rsp)
 	free(rsp);
 }
 
+/* ============== NETDEV_CMD_QUEUE_GET ============== */
+/* NETDEV_CMD_QUEUE_GET - do */
+void netdev_queue_get_req_free(struct netdev_queue_get_req *req)
+{
+	free(req);
+}
+
+void netdev_queue_get_rsp_free(struct netdev_queue_get_rsp *rsp)
+{
+	free(rsp);
+}
+
+int netdev_queue_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
+{
+	struct ynl_parse_arg *yarg = data;
+	struct netdev_queue_get_rsp *dst;
+	const struct nlattr *attr;
+
+	dst = yarg->data;
+
+	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
+		unsigned int type = mnl_attr_get_type(attr);
+
+		if (type == NETDEV_A_QUEUE_QUEUE_ID) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.queue_id = 1;
+			dst->queue_id = mnl_attr_get_u32(attr);
+		} else if (type == NETDEV_A_QUEUE_QUEUE_TYPE) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.queue_type = 1;
+			dst->queue_type = mnl_attr_get_u32(attr);
+		} else if (type == NETDEV_A_QUEUE_NAPI_ID) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.napi_id = 1;
+			dst->napi_id = mnl_attr_get_u32(attr);
+		} else if (type == NETDEV_A_QUEUE_IFINDEX) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.ifindex = 1;
+			dst->ifindex = mnl_attr_get_u32(attr);
+		} else if (type == NETDEV_A_QUEUE_TX_MAXRATE) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.tx_maxrate = 1;
+			dst->tx_maxrate = mnl_attr_get_u32(attr);
+		}
+	}
+
+	return MNL_CB_OK;
+}
+
+struct netdev_queue_get_rsp *
+netdev_queue_get(struct ynl_sock *ys, struct netdev_queue_get_req *req)
+{
+	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
+	struct netdev_queue_get_rsp *rsp;
+	struct nlmsghdr *nlh;
+	int err;
+
+	nlh = ynl_gemsg_start_req(ys, ys->family_id, NETDEV_CMD_QUEUE_GET, 1);
+	ys->req_policy = &netdev_queue_nest;
+	yrs.yarg.rsp_policy = &netdev_queue_nest;
+
+	if (req->_present.ifindex)
+		mnl_attr_put_u32(nlh, NETDEV_A_QUEUE_IFINDEX, req->ifindex);
+	if (req->_present.queue_type)
+		mnl_attr_put_u32(nlh, NETDEV_A_QUEUE_QUEUE_TYPE, req->queue_type);
+	if (req->_present.queue_id)
+		mnl_attr_put_u32(nlh, NETDEV_A_QUEUE_QUEUE_ID, req->queue_id);
+
+	rsp = calloc(1, sizeof(*rsp));
+	yrs.yarg.data = rsp;
+	yrs.cb = netdev_queue_get_rsp_parse;
+	yrs.rsp_cmd = NETDEV_CMD_QUEUE_GET;
+
+	err = ynl_exec(ys, nlh, &yrs);
+	if (err < 0)
+		goto err_free;
+
+	return rsp;
+
+err_free:
+	netdev_queue_get_rsp_free(rsp);
+	return NULL;
+}
+
+/* NETDEV_CMD_QUEUE_GET - dump */
+void netdev_queue_get_list_free(struct netdev_queue_get_list *rsp)
+{
+	struct netdev_queue_get_list *next = rsp;
+
+	while ((void *)next != YNL_LIST_END) {
+		rsp = next;
+		next = rsp->next;
+
+		free(rsp);
+	}
+}
+
+struct netdev_queue_get_list *
+netdev_queue_get_dump(struct ynl_sock *ys,
+		      struct netdev_queue_get_req_dump *req)
+{
+	struct ynl_dump_state yds = {};
+	struct nlmsghdr *nlh;
+	int err;
+
+	yds.ys = ys;
+	yds.alloc_sz = sizeof(struct netdev_queue_get_list);
+	yds.cb = netdev_queue_get_rsp_parse;
+	yds.rsp_cmd = NETDEV_CMD_QUEUE_GET;
+	yds.rsp_policy = &netdev_queue_nest;
+
+	nlh = ynl_gemsg_start_dump(ys, ys->family_id, NETDEV_CMD_QUEUE_GET, 1);
+	ys->req_policy = &netdev_queue_nest;
+
+	if (req->_present.ifindex)
+		mnl_attr_put_u32(nlh, NETDEV_A_QUEUE_IFINDEX, req->ifindex);
+
+	err = ynl_exec_dump(ys, nlh, &yds);
+	if (err < 0)
+		goto free_list;
+
+	return yds.first;
+
+free_list:
+	netdev_queue_get_list_free(yds.first);
+	return NULL;
+}
+
 static const struct ynl_ntf_info netdev_ntf_info[] =  {
 	[NETDEV_CMD_DEV_ADD_NTF] =  {
 		.alloc_sz	= sizeof(struct netdev_dev_get_ntf),
diff --git a/tools/net/ynl/generated/netdev-user.h b/tools/net/ynl/generated/netdev-user.h
index b4351ff34595..1650850820bc 100644
--- a/tools/net/ynl/generated/netdev-user.h
+++ b/tools/net/ynl/generated/netdev-user.h
@@ -19,6 +19,7 @@ extern const struct ynl_family ynl_netdev_family;
 const char *netdev_op_str(int op);
 const char *netdev_xdp_act_str(enum netdev_xdp_act value);
 const char *netdev_xdp_rx_metadata_str(enum netdev_xdp_rx_metadata value);
+const char *netdev_queue_type_str(enum netdev_queue_type value);
 
 /* Common nested types */
 /* ============== NETDEV_CMD_DEV_GET ============== */
@@ -87,4 +88,105 @@ struct netdev_dev_get_ntf {
 
 void netdev_dev_get_ntf_free(struct netdev_dev_get_ntf *rsp);
 
+/* ============== NETDEV_CMD_QUEUE_GET ============== */
+/* NETDEV_CMD_QUEUE_GET - do */
+struct netdev_queue_get_req {
+	struct {
+		__u32 ifindex:1;
+		__u32 queue_type:1;
+		__u32 queue_id:1;
+	} _present;
+
+	__u32 ifindex;
+	enum netdev_queue_type queue_type;
+	__u32 queue_id;
+};
+
+static inline struct netdev_queue_get_req *netdev_queue_get_req_alloc(void)
+{
+	return calloc(1, sizeof(struct netdev_queue_get_req));
+}
+void netdev_queue_get_req_free(struct netdev_queue_get_req *req);
+
+static inline void
+netdev_queue_get_req_set_ifindex(struct netdev_queue_get_req *req,
+				 __u32 ifindex)
+{
+	req->_present.ifindex = 1;
+	req->ifindex = ifindex;
+}
+static inline void
+netdev_queue_get_req_set_queue_type(struct netdev_queue_get_req *req,
+				    enum netdev_queue_type queue_type)
+{
+	req->_present.queue_type = 1;
+	req->queue_type = queue_type;
+}
+static inline void
+netdev_queue_get_req_set_queue_id(struct netdev_queue_get_req *req,
+				  __u32 queue_id)
+{
+	req->_present.queue_id = 1;
+	req->queue_id = queue_id;
+}
+
+struct netdev_queue_get_rsp {
+	struct {
+		__u32 queue_id:1;
+		__u32 queue_type:1;
+		__u32 napi_id:1;
+		__u32 ifindex:1;
+		__u32 tx_maxrate:1;
+	} _present;
+
+	__u32 queue_id;
+	enum netdev_queue_type queue_type;
+	__u32 napi_id;
+	__u32 ifindex;
+	__u32 tx_maxrate;
+};
+
+void netdev_queue_get_rsp_free(struct netdev_queue_get_rsp *rsp);
+
+/*
+ * queue information
+ */
+struct netdev_queue_get_rsp *
+netdev_queue_get(struct ynl_sock *ys, struct netdev_queue_get_req *req);
+
+/* NETDEV_CMD_QUEUE_GET - dump */
+struct netdev_queue_get_req_dump {
+	struct {
+		__u32 ifindex:1;
+	} _present;
+
+	__u32 ifindex;
+};
+
+static inline struct netdev_queue_get_req_dump *
+netdev_queue_get_req_dump_alloc(void)
+{
+	return calloc(1, sizeof(struct netdev_queue_get_req_dump));
+}
+void netdev_queue_get_req_dump_free(struct netdev_queue_get_req_dump *req);
+
+static inline void
+netdev_queue_get_req_dump_set_ifindex(struct netdev_queue_get_req_dump *req,
+				      __u32 ifindex)
+{
+	req->_present.ifindex = 1;
+	req->ifindex = ifindex;
+}
+
+struct netdev_queue_get_list {
+	struct netdev_queue_get_list *next;
+	struct netdev_queue_get_rsp obj __attribute__ ((aligned (8)));
+};
+
+void netdev_queue_get_list_free(struct netdev_queue_get_list *rsp);
+
+struct netdev_queue_get_list *
+netdev_queue_get_dump(struct ynl_sock *ys,
+		      struct netdev_queue_get_req_dump *req);
+
 #endif /* _LINUX_NETDEV_GEN_H */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 02/10] net: Add queue and napi association
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
  2023-10-06  9:14 ` [net-next PATCH v4 01/10] netdev-genl: spec: Extend netdev netlink spec in YAML for queue Amritha Nambiar
@ 2023-10-06  9:14 ` Amritha Nambiar
  2023-10-11  2:17   ` Jakub Kicinski
  2023-10-06  9:14 ` [net-next PATCH v4 03/10] ice: Add support in the driver for associating queue with napi Amritha Nambiar
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:14 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Add the napi pointer in netdev queue for tracking the napi
instance for each queue. This achieves the queue<->napi mapping.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 include/linux/netdevice.h     |    5 +++++
 include/net/netdev_rx_queue.h |    2 ++
 net/core/dev.c                |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 41 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e070a4540fba..264ae0bdabe8 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -645,6 +645,8 @@ struct netdev_queue {
 #ifdef CONFIG_XDP_SOCKETS
 	struct xsk_buff_pool    *pool;
 #endif
+	/* NAPI instance for the queue */
+	struct napi_struct      *napi;
 /*
  * write-mostly part
  */
@@ -2619,6 +2621,9 @@ static inline void *netdev_priv(const struct net_device *dev)
  */
 #define SET_NETDEV_DEVTYPE(net, devtype)	((net)->dev.type = (devtype))
 
+int netif_queue_set_napi(unsigned int queue_index, enum netdev_queue_type type,
+			 struct napi_struct *napi);
+
 /* Default NAPI poll() weight
  * Device drivers are strongly advised to not use bigger value
  */
diff --git a/include/net/netdev_rx_queue.h b/include/net/netdev_rx_queue.h
index cdcafb30d437..2e65b03d214d 100644
--- a/include/net/netdev_rx_queue.h
+++ b/include/net/netdev_rx_queue.h
@@ -21,6 +21,8 @@ struct netdev_rx_queue {
 #ifdef CONFIG_XDP_SOCKETS
 	struct xsk_buff_pool            *pool;
 #endif
+	/* NAPI instance for the queue */
+	struct napi_struct		*napi;
 } ____cacheline_aligned_in_smp;
 
 /*
diff --git a/net/core/dev.c b/net/core/dev.c
index 606a366cc209..9b63a7b76c01 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6394,6 +6394,40 @@ int dev_set_threaded(struct net_device *dev, bool threaded)
 }
 EXPORT_SYMBOL(dev_set_threaded);
 
+/**
+ * netif_queue_set_napi - Associate queue with the napi
+ * @queue_index: Index of queue
+ * @type: queue type as RX or TX
+ * @napi: NAPI context
+ *
+ * Set queue with its corresponding napi context
+ */
+int netif_queue_set_napi(unsigned int queue_index, enum netdev_queue_type type,
+			 struct napi_struct *napi)
+{
+	struct net_device *dev = napi->dev;
+	struct netdev_rx_queue *rxq;
+	struct netdev_queue *txq;
+
+	if (!dev)
+		return -EINVAL;
+
+	switch (type) {
+	case NETDEV_QUEUE_TYPE_RX:
+		rxq = __netif_get_rx_queue(dev, queue_index);
+		rxq->napi = napi;
+		break;
+	case NETDEV_QUEUE_TYPE_TX:
+		txq = netdev_get_tx_queue(dev, queue_index);
+		txq->napi = napi;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(netif_queue_set_napi);
+
 void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
 			   int (*poll)(struct napi_struct *, int), int weight)
 {


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 03/10] ice: Add support in the driver for associating queue with napi
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
  2023-10-06  9:14 ` [net-next PATCH v4 01/10] netdev-genl: spec: Extend netdev netlink spec in YAML for queue Amritha Nambiar
  2023-10-06  9:14 ` [net-next PATCH v4 02/10] net: Add queue and napi association Amritha Nambiar
@ 2023-10-06  9:14 ` Amritha Nambiar
  2023-10-06  9:14 ` [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue Amritha Nambiar
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:14 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

After the napi context is initialized, map the napi instance
with the queue/queue-set on the corresponding irq line.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_lib.c  |   59 +++++++++++++++++++++++++++++
 drivers/net/ethernet/intel/ice/ice_lib.h  |    4 ++
 drivers/net/ethernet/intel/ice/ice_main.c |    4 +-
 3 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index acc3ffc940e7..f2554ecdd2bb 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -2448,6 +2448,12 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
 			goto unroll_vector_base;
 
 		ice_vsi_map_rings_to_vectors(vsi);
+
+		/* Associate q_vector rings to napi */
+		ret = ice_vsi_add_napi_queues(vsi);
+		if (ret)
+			goto unroll_vector_base;
+
 		vsi->stat_offsets_loaded = false;
 
 		if (ice_is_xdp_ena_vsi(vsi)) {
@@ -2927,6 +2933,59 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi)
 		synchronize_irq(vsi->q_vectors[i]->irq.virq);
 }
 
+/**
+ * ice_q_vector_add_napi_queues - Add queue[s] associated with the napi
+ * @q_vector: q_vector pointer
+ *
+ * Associate the q_vector napi with all the queue[s] on the vector
+ * Returns 0 on success or < 0 on error
+ */
+int ice_q_vector_add_napi_queues(struct ice_q_vector *q_vector)
+{
+	struct ice_rx_ring *rx_ring;
+	struct ice_tx_ring *tx_ring;
+	int ret = 0;
+
+	ice_for_each_rx_ring(rx_ring, q_vector->rx) {
+		ret = netif_queue_set_napi(rx_ring->q_index,
+					   NETDEV_QUEUE_TYPE_RX,
+					   &q_vector->napi);
+		if (ret)
+			return ret;
+	}
+	ice_for_each_tx_ring(tx_ring, q_vector->tx) {
+		ret = netif_queue_set_napi(tx_ring->q_index,
+					   NETDEV_QUEUE_TYPE_TX,
+					   &q_vector->napi);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+/**
+ * ice_vsi_add_napi_queues
+ * @vsi: VSI pointer
+ *
+ * Associate queue[s] with napi for all vectors
+ * Returns 0 on success or < 0 on error
+ */
+int ice_vsi_add_napi_queues(struct ice_vsi *vsi)
+{
+	int i, ret = 0;
+
+	if (!vsi->netdev)
+		return ret;
+
+	ice_for_each_q_vector(vsi, i) {
+		ret = ice_q_vector_add_napi_queues(vsi->q_vectors[i]);
+		if (ret)
+			return ret;
+	}
+	return ret;
+}
+
 /**
  * ice_vsi_release - Delete a VSI and free its resources
  * @vsi: the VSI being removed
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
index f24f5d1e6f9c..21d164ac1eed 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_lib.h
@@ -91,6 +91,10 @@ void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc);
 struct ice_vsi *
 ice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params);
 
+int ice_q_vector_add_napi_queues(struct ice_q_vector *q_vector);
+
+int ice_vsi_add_napi_queues(struct ice_vsi *vsi);
+
 int ice_vsi_release(struct ice_vsi *vsi);
 
 void ice_vsi_close(struct ice_vsi *vsi);
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index c726913bc635..059397d07e69 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3374,9 +3374,11 @@ static void ice_napi_add(struct ice_vsi *vsi)
 	if (!vsi->netdev)
 		return;
 
-	ice_for_each_q_vector(vsi, v_idx)
+	ice_for_each_q_vector(vsi, v_idx) {
 		netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi,
 			       ice_napi_poll);
+		ice_q_vector_add_napi_queues(vsi->q_vectors[v_idx]);
+	}
 }
 
 /**


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
                   ` (2 preceding siblings ...)
  2023-10-06  9:14 ` [net-next PATCH v4 03/10] ice: Add support in the driver for associating queue with napi Amritha Nambiar
@ 2023-10-06  9:14 ` Amritha Nambiar
  2023-10-11  2:25   ` Jakub Kicinski
  2023-10-06  9:15 ` [net-next PATCH v4 05/10] netdev-genl: spec: Extend netdev netlink spec in YAML for NAPI Amritha Nambiar
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:14 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Implement the netdev netlink framework functions for
exposing queue information.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 net/core/netdev-genl.c |  207 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 204 insertions(+), 3 deletions(-)

diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 336c608e6a6b..8e8eddf68018 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -6,9 +6,23 @@
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/xdp.h>
+#include <net/netdev_rx_queue.h>
 
 #include "netdev-genl-gen.h"
 
+struct netdev_nl_dump_ctx {
+	unsigned long	ifindex;
+	unsigned int	rxq_idx;
+	unsigned int	txq_idx;
+};
+
+static struct netdev_nl_dump_ctx *netdev_dump_ctx(struct netlink_callback *cb)
+{
+	NL_ASSERT_DUMP_CTX_FITS(struct netdev_nl_dump_ctx);
+
+	return (struct netdev_nl_dump_ctx *)cb->ctx;
+}
+
 static int
 netdev_nl_dev_fill(struct net_device *netdev, struct sk_buff *rsp,
 		   const struct genl_info *info)
@@ -111,12 +125,13 @@ int netdev_nl_dev_get_doit(struct sk_buff *skb, struct genl_info *info)
 
 int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 {
+	struct netdev_nl_dump_ctx *ctx = netdev_dump_ctx(cb);
 	struct net *net = sock_net(skb->sk);
 	struct net_device *netdev;
 	int err = 0;
 
 	rtnl_lock();
-	for_each_netdev_dump(net, netdev, cb->args[0]) {
+	for_each_netdev_dump(net, netdev, ctx->ifindex) {
 		err = netdev_nl_dev_fill(netdev, skb, genl_info_dump(cb));
 		if (err < 0)
 			break;
@@ -129,14 +144,200 @@ int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+static int
+netdev_nl_queue_fill_one(struct sk_buff *rsp, struct net_device *netdev,
+			 u32 q_idx, u32 q_type, const struct genl_info *info)
+{
+	struct netdev_rx_queue *rxq;
+	struct netdev_queue *txq;
+	void *hdr;
+
+	hdr = genlmsg_iput(rsp, info);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	if (nla_put_u32(rsp, NETDEV_A_QUEUE_QUEUE_ID, q_idx))
+		goto nla_put_failure;
+
+	if (nla_put_u32(rsp, NETDEV_A_QUEUE_QUEUE_TYPE, q_type))
+		goto nla_put_failure;
+
+	if (nla_put_u32(rsp, NETDEV_A_QUEUE_IFINDEX, netdev->ifindex))
+		goto nla_put_failure;
+
+	switch (q_type) {
+	case NETDEV_QUEUE_TYPE_RX:
+		rxq = __netif_get_rx_queue(netdev, q_idx);
+		if (rxq->napi && nla_put_u32(rsp, NETDEV_A_QUEUE_NAPI_ID,
+					     rxq->napi->napi_id))
+			goto nla_put_failure;
+		break;
+	case NETDEV_QUEUE_TYPE_TX:
+		txq = netdev_get_tx_queue(netdev, q_idx);
+		if (txq->napi && nla_put_u32(rsp, NETDEV_A_QUEUE_NAPI_ID,
+					     txq->napi->napi_id))
+			goto nla_put_failure;
+
+		if (nla_put_u32(rsp, NETDEV_A_QUEUE_TX_MAXRATE,
+				txq->tx_maxrate))
+			goto nla_put_failure;
+		break;
+	}
+
+	genlmsg_end(rsp, hdr);
+
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(rsp, hdr);
+	return -EMSGSIZE;
+}
+
+static int netdev_nl_queue_validate(struct net_device *netdev, u32 q_id,
+				    u32 q_type)
+{
+	switch (q_type) {
+	case NETDEV_QUEUE_TYPE_RX:
+		if (q_id >= netdev->real_num_rx_queues)
+			return -EINVAL;
+		return 0;
+	case NETDEV_QUEUE_TYPE_TX:
+		if (q_id >= netdev->real_num_tx_queues)
+			return -EINVAL;
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int
+netdev_nl_queue_fill(struct sk_buff *rsp, struct net_device *netdev, u32 q_idx,
+		     u32 q_type, const struct genl_info *info)
+{
+	int err;
+
+	err = netdev_nl_queue_validate(netdev, q_idx, q_type);
+	if (err)
+		return err;
+
+	return netdev_nl_queue_fill_one(rsp, netdev, q_idx, q_type, info);
+}
+
 int netdev_nl_queue_get_doit(struct sk_buff *skb, struct genl_info *info)
 {
-	return -EOPNOTSUPP;
+	u32 q_id, q_type, ifindex;
+	struct net_device *netdev;
+	struct sk_buff *rsp;
+	int err;
+
+	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_QUEUE_ID))
+		return -EINVAL;
+
+	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_QUEUE_TYPE))
+		return -EINVAL;
+
+	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_IFINDEX))
+		return -EINVAL;
+
+	q_id = nla_get_u32(info->attrs[NETDEV_A_QUEUE_QUEUE_ID]);
+
+	q_type = nla_get_u32(info->attrs[NETDEV_A_QUEUE_QUEUE_TYPE]);
+
+	ifindex = nla_get_u32(info->attrs[NETDEV_A_QUEUE_IFINDEX]);
+
+	rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!rsp)
+		return -ENOMEM;
+
+	rtnl_lock();
+
+	netdev = __dev_get_by_index(genl_info_net(info), ifindex);
+	if (netdev)
+		err  = netdev_nl_queue_fill(rsp, netdev, q_id, q_type, info);
+	else
+		err = -ENODEV;
+
+	rtnl_unlock();
+
+	if (err)
+		goto err_free_msg;
+
+	return genlmsg_reply(rsp, info);
+
+err_free_msg:
+	nlmsg_free(rsp);
+	return err;
+}
+
+static int
+netdev_nl_queue_dump_one(struct net_device *netdev, struct sk_buff *rsp,
+			 const struct genl_info *info, unsigned int *start_rx,
+			 unsigned int *start_tx)
+{
+	int err = 0;
+	int i;
+
+	for (i = *start_rx; i < netdev->real_num_rx_queues;) {
+		err = netdev_nl_queue_fill_one(rsp, netdev, i,
+					       NETDEV_QUEUE_TYPE_RX, info);
+		if (err)
+			goto out_err;
+		*start_rx = i++;
+	}
+	for (i = *start_tx; i < netdev->real_num_tx_queues;) {
+		err = netdev_nl_queue_fill_one(rsp, netdev, i,
+					       NETDEV_QUEUE_TYPE_TX, info);
+		if (err)
+			goto out_err;
+		*start_tx = i++;
+	}
+out_err:
+	return err;
 }
 
 int netdev_nl_queue_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	return -EOPNOTSUPP;
+	struct netdev_nl_dump_ctx *ctx = netdev_dump_ctx(cb);
+	const struct genl_info *info = genl_info_dump(cb);
+	struct net *net = sock_net(skb->sk);
+	unsigned int rxq_idx = ctx->rxq_idx;
+	unsigned int txq_idx = ctx->txq_idx;
+	struct net_device *netdev;
+	u32 ifindex = 0;
+	int err = 0;
+
+	if (info->attrs[NETDEV_A_QUEUE_IFINDEX])
+		ifindex = nla_get_u32(info->attrs[NETDEV_A_QUEUE_IFINDEX]);
+
+	rtnl_lock();
+	if (ifindex) {
+		netdev = __dev_get_by_index(net, ifindex);
+		if (netdev)
+			err = netdev_nl_queue_dump_one(netdev, skb, info,
+						       &rxq_idx, &txq_idx);
+		else
+			err = -ENODEV;
+	} else {
+		for_each_netdev_dump(net, netdev, ctx->ifindex) {
+			err = netdev_nl_queue_dump_one(netdev, skb, info,
+						       &rxq_idx, &txq_idx);
+
+			if (err < 0)
+				break;
+			if (!err) {
+				rxq_idx = 0;
+				txq_idx = 0;
+			}
+		}
+	}
+	rtnl_unlock();
+
+	if (err != -EMSGSIZE)
+		return err;
+
+	ctx->rxq_idx = rxq_idx;
+	ctx->txq_idx = txq_idx;
+	return skb->len;
 }
 
 static int netdev_genl_netdevice_event(struct notifier_block *nb,


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 05/10] netdev-genl: spec: Extend netdev netlink spec in YAML for NAPI
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
                   ` (3 preceding siblings ...)
  2023-10-06  9:14 ` [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue Amritha Nambiar
@ 2023-10-06  9:15 ` Amritha Nambiar
  2023-10-06  9:15 ` [net-next PATCH v4 06/10] netdev-genl: Add netlink framework functions for napi Amritha Nambiar
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:15 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Add support in netlink spec(netdev.yaml) for napi related information.
Add code generated from the spec.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 Documentation/netlink/specs/netdev.yaml |   30 ++++++++
 include/uapi/linux/netdev.h             |    9 ++
 net/core/netdev-genl-gen.c              |   24 ++++++
 net/core/netdev-genl-gen.h              |    2 +
 net/core/netdev-genl.c                  |   10 +++
 tools/include/uapi/linux/netdev.h       |    9 ++
 tools/net/ynl/generated/netdev-user.c   |  124 +++++++++++++++++++++++++++++++
 tools/net/ynl/generated/netdev-user.h   |   75 +++++++++++++++++++
 8 files changed, 283 insertions(+)

diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml
index 4694acfe0e50..f7b6db071a37 100644
--- a/Documentation/netlink/specs/netdev.yaml
+++ b/Documentation/netlink/specs/netdev.yaml
@@ -91,6 +91,19 @@ attribute-sets:
         type: u64
         enum: xdp-rx-metadata
 
+  -
+    name: napi
+    attributes:
+      -
+        name: ifindex
+        doc: netdev ifindex
+        type: u32
+        checks:
+          min: 1
+      -
+        name: napi-id
+        doc: napi id
+        type: u32
   -
     name: queue
     attributes:
@@ -172,6 +185,23 @@ operations:
           attributes:
             - ifindex
         reply: *queue-get-op
+    -
+      name: napi-get
+      doc: napi information such as napi-id
+      attribute-set: napi
+      do:
+        request:
+          attributes:
+            - napi-id
+        reply: &napi-get-op
+          attributes:
+            - napi-id
+            - ifindex
+      dump:
+        request:
+          attributes:
+            - ifindex
+        reply: *napi-get-op
 
 mcast-groups:
   list:
diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h
index 69f657a2020f..a58dfbc423b7 100644
--- a/include/uapi/linux/netdev.h
+++ b/include/uapi/linux/netdev.h
@@ -69,6 +69,14 @@ enum {
 	NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
 };
 
+enum {
+	NETDEV_A_NAPI_IFINDEX = 1,
+	NETDEV_A_NAPI_NAPI_ID,
+
+	__NETDEV_A_NAPI_MAX,
+	NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
+};
+
 enum {
 	NETDEV_A_QUEUE_QUEUE_ID = 1,
 	NETDEV_A_QUEUE_IFINDEX,
@@ -86,6 +94,7 @@ enum {
 	NETDEV_CMD_DEV_DEL_NTF,
 	NETDEV_CMD_DEV_CHANGE_NTF,
 	NETDEV_CMD_QUEUE_GET,
+	NETDEV_CMD_NAPI_GET,
 
 	__NETDEV_CMD_MAX,
 	NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)
diff --git a/net/core/netdev-genl-gen.c b/net/core/netdev-genl-gen.c
index 85d556a051db..77a340f6c285 100644
--- a/net/core/netdev-genl-gen.c
+++ b/net/core/netdev-genl-gen.c
@@ -27,6 +27,16 @@ static const struct nla_policy netdev_queue_get_dump_nl_policy[NETDEV_A_QUEUE_IF
 	[NETDEV_A_QUEUE_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1),
 };
 
+/* NETDEV_CMD_NAPI_GET - do */
+static const struct nla_policy netdev_napi_get_do_nl_policy[NETDEV_A_NAPI_NAPI_ID + 1] = {
+	[NETDEV_A_NAPI_NAPI_ID] = { .type = NLA_U32, },
+};
+
+/* NETDEV_CMD_NAPI_GET - dump */
+static const struct nla_policy netdev_napi_get_dump_nl_policy[NETDEV_A_NAPI_IFINDEX + 1] = {
+	[NETDEV_A_NAPI_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1),
+};
+
 /* Ops table for netdev */
 static const struct genl_split_ops netdev_nl_ops[] = {
 	{
@@ -55,6 +65,20 @@ static const struct genl_split_ops netdev_nl_ops[] = {
 		.maxattr	= NETDEV_A_QUEUE_IFINDEX,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
+	{
+		.cmd		= NETDEV_CMD_NAPI_GET,
+		.doit		= netdev_nl_napi_get_doit,
+		.policy		= netdev_napi_get_do_nl_policy,
+		.maxattr	= NETDEV_A_NAPI_NAPI_ID,
+		.flags		= GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd		= NETDEV_CMD_NAPI_GET,
+		.dumpit		= netdev_nl_napi_get_dumpit,
+		.policy		= netdev_napi_get_dump_nl_policy,
+		.maxattr	= NETDEV_A_NAPI_IFINDEX,
+		.flags		= GENL_CMD_CAP_DUMP,
+	},
 };
 
 static const struct genl_multicast_group netdev_nl_mcgrps[] = {
diff --git a/net/core/netdev-genl-gen.h b/net/core/netdev-genl-gen.h
index 263c94f77bad..ffc94956d1f5 100644
--- a/net/core/netdev-genl-gen.h
+++ b/net/core/netdev-genl-gen.h
@@ -16,6 +16,8 @@ int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 int netdev_nl_queue_get_doit(struct sk_buff *skb, struct genl_info *info);
 int netdev_nl_queue_get_dumpit(struct sk_buff *skb,
 			       struct netlink_callback *cb);
+int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info);
+int netdev_nl_napi_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
 
 enum {
 	NETDEV_NLGRP_MGMT,
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 8e8eddf68018..fdd67c67e9aa 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -144,6 +144,16 @@ int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info)
+{
+	return -EOPNOTSUPP;
+}
+
+int netdev_nl_napi_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	return -EOPNOTSUPP;
+}
+
 static int
 netdev_nl_queue_fill_one(struct sk_buff *rsp, struct net_device *netdev,
 			 u32 q_idx, u32 q_type, const struct genl_info *info)
diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h
index 69f657a2020f..a58dfbc423b7 100644
--- a/tools/include/uapi/linux/netdev.h
+++ b/tools/include/uapi/linux/netdev.h
@@ -69,6 +69,14 @@ enum {
 	NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
 };
 
+enum {
+	NETDEV_A_NAPI_IFINDEX = 1,
+	NETDEV_A_NAPI_NAPI_ID,
+
+	__NETDEV_A_NAPI_MAX,
+	NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
+};
+
 enum {
 	NETDEV_A_QUEUE_QUEUE_ID = 1,
 	NETDEV_A_QUEUE_IFINDEX,
@@ -86,6 +94,7 @@ enum {
 	NETDEV_CMD_DEV_DEL_NTF,
 	NETDEV_CMD_DEV_CHANGE_NTF,
 	NETDEV_CMD_QUEUE_GET,
+	NETDEV_CMD_NAPI_GET,
 
 	__NETDEV_CMD_MAX,
 	NETDEV_CMD_MAX = (__NETDEV_CMD_MAX - 1)
diff --git a/tools/net/ynl/generated/netdev-user.c b/tools/net/ynl/generated/netdev-user.c
index b597bab2b85b..29c5e0212328 100644
--- a/tools/net/ynl/generated/netdev-user.c
+++ b/tools/net/ynl/generated/netdev-user.c
@@ -19,6 +19,7 @@ static const char * const netdev_op_strmap[] = {
 	[NETDEV_CMD_DEV_DEL_NTF] = "dev-del-ntf",
 	[NETDEV_CMD_DEV_CHANGE_NTF] = "dev-change-ntf",
 	[NETDEV_CMD_QUEUE_GET] = "queue-get",
+	[NETDEV_CMD_NAPI_GET] = "napi-get",
 };
 
 const char *netdev_op_str(int op)
@@ -98,6 +99,16 @@ struct ynl_policy_nest netdev_queue_nest = {
 	.table = netdev_queue_policy,
 };
 
+struct ynl_policy_attr netdev_napi_policy[NETDEV_A_NAPI_MAX + 1] = {
+	[NETDEV_A_NAPI_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, },
+	[NETDEV_A_NAPI_NAPI_ID] = { .name = "napi-id", .type = YNL_PT_U32, },
+};
+
+struct ynl_policy_nest netdev_napi_nest = {
+	.max_attr = NETDEV_A_NAPI_MAX,
+	.table = netdev_napi_policy,
+};
+
 /* Common nested types */
 /* ============== NETDEV_CMD_DEV_GET ============== */
 /* NETDEV_CMD_DEV_GET - do */
@@ -356,6 +367,119 @@ netdev_queue_get_dump(struct ynl_sock *ys,
 	return NULL;
 }
 
+/* ============== NETDEV_CMD_NAPI_GET ============== */
+/* NETDEV_CMD_NAPI_GET - do */
+void netdev_napi_get_req_free(struct netdev_napi_get_req *req)
+{
+	free(req);
+}
+
+void netdev_napi_get_rsp_free(struct netdev_napi_get_rsp *rsp)
+{
+	free(rsp);
+}
+
+int netdev_napi_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
+{
+	struct ynl_parse_arg *yarg = data;
+	struct netdev_napi_get_rsp *dst;
+	const struct nlattr *attr;
+
+	dst = yarg->data;
+
+	mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
+		unsigned int type = mnl_attr_get_type(attr);
+
+		if (type == NETDEV_A_NAPI_NAPI_ID) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.napi_id = 1;
+			dst->napi_id = mnl_attr_get_u32(attr);
+		} else if (type == NETDEV_A_NAPI_IFINDEX) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.ifindex = 1;
+			dst->ifindex = mnl_attr_get_u32(attr);
+		}
+	}
+
+	return MNL_CB_OK;
+}
+
+struct netdev_napi_get_rsp *
+netdev_napi_get(struct ynl_sock *ys, struct netdev_napi_get_req *req)
+{
+	struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };
+	struct netdev_napi_get_rsp *rsp;
+	struct nlmsghdr *nlh;
+	int err;
+
+	nlh = ynl_gemsg_start_req(ys, ys->family_id, NETDEV_CMD_NAPI_GET, 1);
+	ys->req_policy = &netdev_napi_nest;
+	yrs.yarg.rsp_policy = &netdev_napi_nest;
+
+	if (req->_present.napi_id)
+		mnl_attr_put_u32(nlh, NETDEV_A_NAPI_NAPI_ID, req->napi_id);
+
+	rsp = calloc(1, sizeof(*rsp));
+	yrs.yarg.data = rsp;
+	yrs.cb = netdev_napi_get_rsp_parse;
+	yrs.rsp_cmd = NETDEV_CMD_NAPI_GET;
+
+	err = ynl_exec(ys, nlh, &yrs);
+	if (err < 0)
+		goto err_free;
+
+	return rsp;
+
+err_free:
+	netdev_napi_get_rsp_free(rsp);
+	return NULL;
+}
+
+/* NETDEV_CMD_NAPI_GET - dump */
+void netdev_napi_get_list_free(struct netdev_napi_get_list *rsp)
+{
+	struct netdev_napi_get_list *next = rsp;
+
+	while ((void *)next != YNL_LIST_END) {
+		rsp = next;
+		next = rsp->next;
+
+		free(rsp);
+	}
+}
+
+struct netdev_napi_get_list *
+netdev_napi_get_dump(struct ynl_sock *ys, struct netdev_napi_get_req_dump *req)
+{
+	struct ynl_dump_state yds = {};
+	struct nlmsghdr *nlh;
+	int err;
+
+	yds.ys = ys;
+	yds.alloc_sz = sizeof(struct netdev_napi_get_list);
+	yds.cb = netdev_napi_get_rsp_parse;
+	yds.rsp_cmd = NETDEV_CMD_NAPI_GET;
+	yds.rsp_policy = &netdev_napi_nest;
+
+	nlh = ynl_gemsg_start_dump(ys, ys->family_id, NETDEV_CMD_NAPI_GET, 1);
+	ys->req_policy = &netdev_napi_nest;
+
+	if (req->_present.ifindex)
+		mnl_attr_put_u32(nlh, NETDEV_A_NAPI_IFINDEX, req->ifindex);
+
+	err = ynl_exec_dump(ys, nlh, &yds);
+	if (err < 0)
+		goto free_list;
+
+	return yds.first;
+
+free_list:
+	netdev_napi_get_list_free(yds.first);
+	return NULL;
+}
+
 static const struct ynl_ntf_info netdev_ntf_info[] =  {
 	[NETDEV_CMD_DEV_ADD_NTF] =  {
 		.alloc_sz	= sizeof(struct netdev_dev_get_ntf),
diff --git a/tools/net/ynl/generated/netdev-user.h b/tools/net/ynl/generated/netdev-user.h
index 1650850820bc..870cf90993b4 100644
--- a/tools/net/ynl/generated/netdev-user.h
+++ b/tools/net/ynl/generated/netdev-user.h
@@ -189,4 +189,79 @@ struct netdev_queue_get_list *
 netdev_queue_get_dump(struct ynl_sock *ys,
 		      struct netdev_queue_get_req_dump *req);
 
+/* ============== NETDEV_CMD_NAPI_GET ============== */
+/* NETDEV_CMD_NAPI_GET - do */
+struct netdev_napi_get_req {
+	struct {
+		__u32 napi_id:1;
+	} _present;
+
+	__u32 napi_id;
+};
+
+static inline struct netdev_napi_get_req *netdev_napi_get_req_alloc(void)
+{
+	return calloc(1, sizeof(struct netdev_napi_get_req));
+}
+void netdev_napi_get_req_free(struct netdev_napi_get_req *req);
+
+static inline void
+netdev_napi_get_req_set_napi_id(struct netdev_napi_get_req *req, __u32 napi_id)
+{
+	req->_present.napi_id = 1;
+	req->napi_id = napi_id;
+}
+
+struct netdev_napi_get_rsp {
+	struct {
+		__u32 napi_id:1;
+		__u32 ifindex:1;
+	} _present;
+
+	__u32 napi_id;
+	__u32 ifindex;
+};
+
+void netdev_napi_get_rsp_free(struct netdev_napi_get_rsp *rsp);
+
+/*
+ * napi information such as napi-id
+ */
+struct netdev_napi_get_rsp *
+netdev_napi_get(struct ynl_sock *ys, struct netdev_napi_get_req *req);
+
+/* NETDEV_CMD_NAPI_GET - dump */
+struct netdev_napi_get_req_dump {
+	struct {
+		__u32 ifindex:1;
+	} _present;
+
+	__u32 ifindex;
+};
+
+static inline struct netdev_napi_get_req_dump *
+netdev_napi_get_req_dump_alloc(void)
+{
+	return calloc(1, sizeof(struct netdev_napi_get_req_dump));
+}
+void netdev_napi_get_req_dump_free(struct netdev_napi_get_req_dump *req);
+
+static inline void
+netdev_napi_get_req_dump_set_ifindex(struct netdev_napi_get_req_dump *req,
+				     __u32 ifindex)
+{
+	req->_present.ifindex = 1;
+	req->ifindex = ifindex;
+}
+
+struct netdev_napi_get_list {
+	struct netdev_napi_get_list *next;
+	struct netdev_napi_get_rsp obj __attribute__ ((aligned (8)));
+};
+
+void netdev_napi_get_list_free(struct netdev_napi_get_list *rsp);
+
+struct netdev_napi_get_list *
+netdev_napi_get_dump(struct ynl_sock *ys, struct netdev_napi_get_req_dump *req);
+
 #endif /* _LINUX_NETDEV_GEN_H */


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 06/10] netdev-genl: Add netlink framework functions for napi
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
                   ` (4 preceding siblings ...)
  2023-10-06  9:15 ` [net-next PATCH v4 05/10] netdev-genl: spec: Extend netdev netlink spec in YAML for NAPI Amritha Nambiar
@ 2023-10-06  9:15 ` Amritha Nambiar
  2023-10-11  2:29   ` Jakub Kicinski
  2023-10-06  9:15 ` [net-next PATCH v4 07/10] netdev-genl: spec: Add irq in netdev netlink YAML spec Amritha Nambiar
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:15 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Implement the netdev netlink framework functions for
napi support. The netdev structure tracks all the napi
instances and napi fields. The napi instances and associated
parameters can be retrieved this way.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 include/linux/netdevice.h |    2 +
 net/core/dev.c            |    4 +-
 net/core/netdev-genl.c    |  117 ++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 119 insertions(+), 4 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 264ae0bdabe8..da211f4d81db 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -536,6 +536,8 @@ static inline bool napi_complete(struct napi_struct *n)
 	return napi_complete_done(n, 0);
 }
 
+struct napi_struct *napi_by_id(unsigned int napi_id);
+
 int dev_set_threaded(struct net_device *dev, bool threaded);
 
 /**
diff --git a/net/core/dev.c b/net/core/dev.c
index 9b63a7b76c01..85448451b9fa 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -165,7 +165,6 @@ static int netif_rx_internal(struct sk_buff *skb);
 static int call_netdevice_notifiers_extack(unsigned long val,
 					   struct net_device *dev,
 					   struct netlink_ext_ack *extack);
-static struct napi_struct *napi_by_id(unsigned int napi_id);
 
 /*
  * The @dev_base_head list is protected by @dev_base_lock and the rtnl
@@ -6133,7 +6132,7 @@ bool napi_complete_done(struct napi_struct *n, int work_done)
 EXPORT_SYMBOL(napi_complete_done);
 
 /* must be called under rcu_read_lock(), as we dont take a reference */
-static struct napi_struct *napi_by_id(unsigned int napi_id)
+struct napi_struct *napi_by_id(unsigned int napi_id)
 {
 	unsigned int hash = napi_id % HASH_SIZE(napi_hash);
 	struct napi_struct *napi;
@@ -6144,6 +6143,7 @@ static struct napi_struct *napi_by_id(unsigned int napi_id)
 
 	return NULL;
 }
+EXPORT_SYMBOL(napi_by_id);
 
 #if defined(CONFIG_NET_RX_BUSY_POLL)
 
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index fdd67c67e9aa..530d6f474bd5 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -7,6 +7,7 @@
 #include <net/sock.h>
 #include <net/xdp.h>
 #include <net/netdev_rx_queue.h>
+#include <net/busy_poll.h>
 
 #include "netdev-genl-gen.h"
 
@@ -14,6 +15,7 @@ struct netdev_nl_dump_ctx {
 	unsigned long	ifindex;
 	unsigned int	rxq_idx;
 	unsigned int	txq_idx;
+	unsigned int	napi_id;
 };
 
 static struct netdev_nl_dump_ctx *netdev_dump_ctx(struct netlink_callback *cb)
@@ -144,14 +146,125 @@ int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+static int
+netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi,
+			const struct genl_info *info)
+{
+	void *hdr;
+
+	if (WARN_ON_ONCE(!napi->dev))
+		return -EINVAL;
+
+	hdr = genlmsg_iput(rsp, info);
+	if (!hdr)
+		return -EMSGSIZE;
+
+	if (napi->napi_id >= MIN_NAPI_ID &&
+	    nla_put_u32(rsp, NETDEV_A_NAPI_NAPI_ID, napi->napi_id))
+		goto nla_put_failure;
+
+	if (nla_put_u32(rsp, NETDEV_A_NAPI_IFINDEX, napi->dev->ifindex))
+		goto nla_put_failure;
+
+	genlmsg_end(rsp, hdr);
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(rsp, hdr);
+	return -EMSGSIZE;
+}
+
 int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info)
 {
-	return -EOPNOTSUPP;
+	struct napi_struct *napi;
+	struct sk_buff *rsp;
+	u32 napi_id;
+	int err;
+
+	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_NAPI_NAPI_ID))
+		return -EINVAL;
+
+	napi_id = nla_get_u32(info->attrs[NETDEV_A_NAPI_NAPI_ID]);
+
+	rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!rsp)
+		return -ENOMEM;
+
+	rcu_read_lock();
+
+	napi = napi_by_id(napi_id);
+	if (napi)
+		err  = netdev_nl_napi_fill_one(rsp, napi, info);
+	else
+		err = -EINVAL;
+
+	rcu_read_unlock();
+
+	if (err)
+		goto err_free_msg;
+
+	return genlmsg_reply(rsp, info);
+
+err_free_msg:
+	nlmsg_free(rsp);
+	return err;
+}
+
+static int
+netdev_nl_napi_dump_one(struct net_device *netdev, struct sk_buff *rsp,
+			const struct genl_info *info, unsigned int *start)
+{
+	struct napi_struct *napi;
+	int err = 0;
+
+	list_for_each_entry(napi, &netdev->napi_list, dev_list) {
+		if (*start && napi->napi_id >= *start)
+			continue;
+
+		err = netdev_nl_napi_fill_one(rsp, napi, info);
+		if (err)
+			break;
+		*start = napi->napi_id;
+	}
+	return err;
 }
 
 int netdev_nl_napi_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	return -EOPNOTSUPP;
+	struct netdev_nl_dump_ctx *ctx = netdev_dump_ctx(cb);
+	const struct genl_info *info = genl_info_dump(cb);
+	struct net *net = sock_net(skb->sk);
+	unsigned int n_id = ctx->napi_id;
+	struct net_device *netdev;
+	u32 ifindex = 0;
+	int err = 0;
+
+	if (info->attrs[NETDEV_A_NAPI_IFINDEX])
+		ifindex = nla_get_u32(info->attrs[NETDEV_A_NAPI_IFINDEX]);
+
+	rtnl_lock();
+	if (ifindex) {
+		netdev = __dev_get_by_index(net, ifindex);
+		if (netdev)
+			err = netdev_nl_napi_dump_one(netdev, skb, info, &n_id);
+		else
+			err = -ENODEV;
+	} else {
+		for_each_netdev_dump(net, netdev, ctx->ifindex) {
+			err = netdev_nl_napi_dump_one(netdev, skb, info, &n_id);
+			if (err < 0)
+				break;
+			if (!err)
+				n_id = 0;
+		}
+	}
+	rtnl_unlock();
+
+	if (err != -EMSGSIZE)
+		return err;
+
+	ctx->napi_id = n_id;
+	return skb->len;
 }
 
 static int


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 07/10] netdev-genl: spec: Add irq in netdev netlink YAML spec
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
                   ` (5 preceding siblings ...)
  2023-10-06  9:15 ` [net-next PATCH v4 06/10] netdev-genl: Add netlink framework functions for napi Amritha Nambiar
@ 2023-10-06  9:15 ` Amritha Nambiar
  2023-10-06  9:15 ` [net-next PATCH v4 08/10] net: Add NAPI IRQ support Amritha Nambiar
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:15 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Add support in netlink spec(netdev.yaml) for interrupt number
among the NAPI attributes. Add code generated from the spec.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 Documentation/netlink/specs/netdev.yaml |    5 +++++
 include/uapi/linux/netdev.h             |    1 +
 tools/include/uapi/linux/netdev.h       |    1 +
 tools/net/ynl/generated/netdev-user.c   |    6 ++++++
 tools/net/ynl/generated/netdev-user.h   |    2 ++
 5 files changed, 15 insertions(+)

diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml
index f7b6db071a37..c3051aadf102 100644
--- a/Documentation/netlink/specs/netdev.yaml
+++ b/Documentation/netlink/specs/netdev.yaml
@@ -104,6 +104,10 @@ attribute-sets:
         name: napi-id
         doc: napi id
         type: u32
+      -
+        name: irq
+        doc: The associated interrupt vector number for the napi
+        type: u32
   -
     name: queue
     attributes:
@@ -197,6 +201,7 @@ operations:
           attributes:
             - napi-id
             - ifindex
+            - irq
       dump:
         request:
           attributes:
diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h
index a58dfbc423b7..1ce483ba6e85 100644
--- a/include/uapi/linux/netdev.h
+++ b/include/uapi/linux/netdev.h
@@ -72,6 +72,7 @@ enum {
 enum {
 	NETDEV_A_NAPI_IFINDEX = 1,
 	NETDEV_A_NAPI_NAPI_ID,
+	NETDEV_A_NAPI_IRQ,
 
 	__NETDEV_A_NAPI_MAX,
 	NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h
index a58dfbc423b7..1ce483ba6e85 100644
--- a/tools/include/uapi/linux/netdev.h
+++ b/tools/include/uapi/linux/netdev.h
@@ -72,6 +72,7 @@ enum {
 enum {
 	NETDEV_A_NAPI_IFINDEX = 1,
 	NETDEV_A_NAPI_NAPI_ID,
+	NETDEV_A_NAPI_IRQ,
 
 	__NETDEV_A_NAPI_MAX,
 	NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
diff --git a/tools/net/ynl/generated/netdev-user.c b/tools/net/ynl/generated/netdev-user.c
index 29c5e0212328..9ce21651fbdc 100644
--- a/tools/net/ynl/generated/netdev-user.c
+++ b/tools/net/ynl/generated/netdev-user.c
@@ -102,6 +102,7 @@ struct ynl_policy_nest netdev_queue_nest = {
 struct ynl_policy_attr netdev_napi_policy[NETDEV_A_NAPI_MAX + 1] = {
 	[NETDEV_A_NAPI_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, },
 	[NETDEV_A_NAPI_NAPI_ID] = { .name = "napi-id", .type = YNL_PT_U32, },
+	[NETDEV_A_NAPI_IRQ] = { .name = "irq", .type = YNL_PT_U32, },
 };
 
 struct ynl_policy_nest netdev_napi_nest = {
@@ -400,6 +401,11 @@ int netdev_napi_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
 				return MNL_CB_ERROR;
 			dst->_present.ifindex = 1;
 			dst->ifindex = mnl_attr_get_u32(attr);
+		} else if (type == NETDEV_A_NAPI_IRQ) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.irq = 1;
+			dst->irq = mnl_attr_get_u32(attr);
 		}
 	}
 
diff --git a/tools/net/ynl/generated/netdev-user.h b/tools/net/ynl/generated/netdev-user.h
index 870cf90993b4..d9db9a84c866 100644
--- a/tools/net/ynl/generated/netdev-user.h
+++ b/tools/net/ynl/generated/netdev-user.h
@@ -216,10 +216,12 @@ struct netdev_napi_get_rsp {
 	struct {
 		__u32 napi_id:1;
 		__u32 ifindex:1;
+		__u32 irq:1;
 	} _present;
 
 	__u32 napi_id;
 	__u32 ifindex;
+	__u32 irq;
 };
 
 void netdev_napi_get_rsp_free(struct netdev_napi_get_rsp *rsp);


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 08/10] net: Add NAPI IRQ support
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
                   ` (6 preceding siblings ...)
  2023-10-06  9:15 ` [net-next PATCH v4 07/10] netdev-genl: spec: Add irq in netdev netlink YAML spec Amritha Nambiar
@ 2023-10-06  9:15 ` Amritha Nambiar
  2023-10-06  9:15 ` [net-next PATCH v4 09/10] netdev-genl: spec: Add PID in netdev netlink YAML spec Amritha Nambiar
  2023-10-06  9:15 ` [net-next PATCH v4 10/10] netdev-genl: Add PID for the NAPI thread Amritha Nambiar
  9 siblings, 0 replies; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:15 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Add support to associate the interrupt vector number for a
NAPI instance.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_lib.c |    3 +++
 include/linux/netdevice.h                |    6 ++++++
 net/core/dev.c                           |    1 +
 net/core/netdev-genl.c                   |    4 ++++
 4 files changed, 14 insertions(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
index f2554ecdd2bb..029d2b4b8789 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -2961,6 +2961,9 @@ int ice_q_vector_add_napi_queues(struct ice_q_vector *q_vector)
 			return ret;
 	}
 
+	/* Also set the interrupt number for the NAPI */
+	netif_napi_set_irq(&q_vector->napi, q_vector->irq.virq);
+
 	return ret;
 }
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index da211f4d81db..1dab653cb6a5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -382,6 +382,7 @@ struct napi_struct {
 	/* control-path-only fields follow */
 	struct list_head	dev_list;
 	struct hlist_node	napi_hash_node;
+	int			irq;
 };
 
 enum {
@@ -2626,6 +2627,11 @@ static inline void *netdev_priv(const struct net_device *dev)
 int netif_queue_set_napi(unsigned int queue_index, enum netdev_queue_type type,
 			 struct napi_struct *napi);
 
+static inline void netif_napi_set_irq(struct napi_struct *napi, int irq)
+{
+	napi->irq = irq;
+}
+
 /* Default NAPI poll() weight
  * Device drivers are strongly advised to not use bigger value
  */
diff --git a/net/core/dev.c b/net/core/dev.c
index 85448451b9fa..8e8410c71b7a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6463,6 +6463,7 @@ void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
 	 */
 	if (dev->threaded && napi_kthread_create(napi))
 		dev->threaded = 0;
+	napi->irq = -1;
 }
 EXPORT_SYMBOL(netif_napi_add_weight);
 
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 530d6f474bd5..336fcaaf169a 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -166,7 +166,11 @@ netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi,
 	if (nla_put_u32(rsp, NETDEV_A_NAPI_IFINDEX, napi->dev->ifindex))
 		goto nla_put_failure;
 
+	if (napi->irq >= 0 && nla_put_u32(rsp, NETDEV_A_NAPI_IRQ, napi->irq))
+		goto nla_put_failure;
+
 	genlmsg_end(rsp, hdr);
+
 	return 0;
 
 nla_put_failure:


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 09/10] netdev-genl: spec: Add PID in netdev netlink YAML spec
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
                   ` (7 preceding siblings ...)
  2023-10-06  9:15 ` [net-next PATCH v4 08/10] net: Add NAPI IRQ support Amritha Nambiar
@ 2023-10-06  9:15 ` Amritha Nambiar
  2023-10-06  9:15 ` [net-next PATCH v4 10/10] netdev-genl: Add PID for the NAPI thread Amritha Nambiar
  9 siblings, 0 replies; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:15 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

Add support in netlink spec(netdev.yaml) for PID of the
NAPI thread. Add code generated from the spec.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 Documentation/netlink/specs/netdev.yaml |    5 +++++
 include/uapi/linux/netdev.h             |    1 +
 tools/include/uapi/linux/netdev.h       |    1 +
 tools/net/ynl/generated/netdev-user.c   |    6 ++++++
 tools/net/ynl/generated/netdev-user.h   |    2 ++
 5 files changed, 15 insertions(+)

diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlink/specs/netdev.yaml
index c3051aadf102..e2bd04b15403 100644
--- a/Documentation/netlink/specs/netdev.yaml
+++ b/Documentation/netlink/specs/netdev.yaml
@@ -108,6 +108,10 @@ attribute-sets:
         name: irq
         doc: The associated interrupt vector number for the napi
         type: u32
+      -
+        name: pid
+        doc: PID of the napi thread
+        type: s32
   -
     name: queue
     attributes:
@@ -202,6 +206,7 @@ operations:
             - napi-id
             - ifindex
             - irq
+            - pid
       dump:
         request:
           attributes:
diff --git a/include/uapi/linux/netdev.h b/include/uapi/linux/netdev.h
index 1ce483ba6e85..6a74b841d04a 100644
--- a/include/uapi/linux/netdev.h
+++ b/include/uapi/linux/netdev.h
@@ -73,6 +73,7 @@ enum {
 	NETDEV_A_NAPI_IFINDEX = 1,
 	NETDEV_A_NAPI_NAPI_ID,
 	NETDEV_A_NAPI_IRQ,
+	NETDEV_A_NAPI_PID,
 
 	__NETDEV_A_NAPI_MAX,
 	NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
diff --git a/tools/include/uapi/linux/netdev.h b/tools/include/uapi/linux/netdev.h
index 1ce483ba6e85..6a74b841d04a 100644
--- a/tools/include/uapi/linux/netdev.h
+++ b/tools/include/uapi/linux/netdev.h
@@ -73,6 +73,7 @@ enum {
 	NETDEV_A_NAPI_IFINDEX = 1,
 	NETDEV_A_NAPI_NAPI_ID,
 	NETDEV_A_NAPI_IRQ,
+	NETDEV_A_NAPI_PID,
 
 	__NETDEV_A_NAPI_MAX,
 	NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
diff --git a/tools/net/ynl/generated/netdev-user.c b/tools/net/ynl/generated/netdev-user.c
index 9ce21651fbdc..d60825b520c9 100644
--- a/tools/net/ynl/generated/netdev-user.c
+++ b/tools/net/ynl/generated/netdev-user.c
@@ -103,6 +103,7 @@ struct ynl_policy_attr netdev_napi_policy[NETDEV_A_NAPI_MAX + 1] = {
 	[NETDEV_A_NAPI_IFINDEX] = { .name = "ifindex", .type = YNL_PT_U32, },
 	[NETDEV_A_NAPI_NAPI_ID] = { .name = "napi-id", .type = YNL_PT_U32, },
 	[NETDEV_A_NAPI_IRQ] = { .name = "irq", .type = YNL_PT_U32, },
+	[NETDEV_A_NAPI_PID] = { .name = "pid", .type = YNL_PT_U32, },
 };
 
 struct ynl_policy_nest netdev_napi_nest = {
@@ -406,6 +407,11 @@ int netdev_napi_get_rsp_parse(const struct nlmsghdr *nlh, void *data)
 				return MNL_CB_ERROR;
 			dst->_present.irq = 1;
 			dst->irq = mnl_attr_get_u32(attr);
+		} else if (type == NETDEV_A_NAPI_PID) {
+			if (ynl_attr_validate(yarg, attr))
+				return MNL_CB_ERROR;
+			dst->_present.pid = 1;
+			dst->pid = mnl_attr_get_u32(attr);
 		}
 	}
 
diff --git a/tools/net/ynl/generated/netdev-user.h b/tools/net/ynl/generated/netdev-user.h
index d9db9a84c866..46d7ea4468b4 100644
--- a/tools/net/ynl/generated/netdev-user.h
+++ b/tools/net/ynl/generated/netdev-user.h
@@ -217,11 +217,13 @@ struct netdev_napi_get_rsp {
 		__u32 napi_id:1;
 		__u32 ifindex:1;
 		__u32 irq:1;
+		__u32 pid:1;
 	} _present;
 
 	__u32 napi_id;
 	__u32 ifindex;
 	__u32 irq;
+	__s32 pid;
 };
 
 void netdev_napi_get_rsp_free(struct netdev_napi_get_rsp *rsp);


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [net-next PATCH v4 10/10] netdev-genl: Add PID for the NAPI thread
  2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
                   ` (8 preceding siblings ...)
  2023-10-06  9:15 ` [net-next PATCH v4 09/10] netdev-genl: spec: Add PID in netdev netlink YAML spec Amritha Nambiar
@ 2023-10-06  9:15 ` Amritha Nambiar
  9 siblings, 0 replies; 24+ messages in thread
From: Amritha Nambiar @ 2023-10-06  9:15 UTC (permalink / raw)
  To: netdev, kuba; +Cc: sridhar.samudrala, amritha.nambiar

In the threaded NAPI mode, expose the PID of the NAPI thread.

Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 net/core/netdev-genl.c |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 336fcaaf169a..d1dec79aac12 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -151,6 +151,7 @@ netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi,
 			const struct genl_info *info)
 {
 	void *hdr;
+	pid_t pid;
 
 	if (WARN_ON_ONCE(!napi->dev))
 		return -EINVAL;
@@ -169,6 +170,12 @@ netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi,
 	if (napi->irq >= 0 && nla_put_u32(rsp, NETDEV_A_NAPI_IRQ, napi->irq))
 		goto nla_put_failure;
 
+	if (napi->thread) {
+		pid = task_pid_nr(napi->thread);
+		if (nla_put_s32(rsp, NETDEV_A_NAPI_PID, pid))
+			goto nla_put_failure;
+	}
+
 	genlmsg_end(rsp, hdr);
 
 	return 0;


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 01/10] netdev-genl: spec: Extend netdev netlink spec in YAML for queue
  2023-10-06  9:14 ` [net-next PATCH v4 01/10] netdev-genl: spec: Extend netdev netlink spec in YAML for queue Amritha Nambiar
@ 2023-10-11  2:12   ` Jakub Kicinski
  2023-10-11 23:28     ` Nambiar, Amritha
  0 siblings, 1 reply; 24+ messages in thread
From: Jakub Kicinski @ 2023-10-11  2:12 UTC (permalink / raw)
  To: Amritha Nambiar; +Cc: netdev, sridhar.samudrala

On Fri, 06 Oct 2023 02:14:43 -0700 Amritha Nambiar wrote:
> Add support in netlink spec(netdev.yaml) for queue information.
> Add code generated from the spec.
> 
> Note: The "queue-type" attribute currently takes values 0 and 1
> for rx and tx queue type respectively. I haven't figured out the
> ynl library changes to support string user input ("rx" and "tx")
> to enum value conversion in the generated C code.

Let's leave the maxrate out of this version entirely, please.
Otherwise looks good.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 02/10] net: Add queue and napi association
  2023-10-06  9:14 ` [net-next PATCH v4 02/10] net: Add queue and napi association Amritha Nambiar
@ 2023-10-11  2:17   ` Jakub Kicinski
  2023-10-11 23:36     ` Nambiar, Amritha
  0 siblings, 1 reply; 24+ messages in thread
From: Jakub Kicinski @ 2023-10-11  2:17 UTC (permalink / raw)
  To: Amritha Nambiar; +Cc: netdev, sridhar.samudrala

On Fri, 06 Oct 2023 02:14:48 -0700 Amritha Nambiar wrote:
>  #endif
> +	/* NAPI instance for the queue */
> +	struct napi_struct		*napi;

What's the protection on this field?
Writers and readers must be under rtnl_lock?

>  } ____cacheline_aligned_in_smp;
>  
>  /*
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 606a366cc209..9b63a7b76c01 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -6394,6 +6394,40 @@ int dev_set_threaded(struct net_device *dev, bool threaded)
>  }
>  EXPORT_SYMBOL(dev_set_threaded);
>  
> +/**
> + * netif_queue_set_napi - Associate queue with the napi
> + * @queue_index: Index of queue
> + * @type: queue type as RX or TX
> + * @napi: NAPI context
> + *
> + * Set queue with its corresponding napi context

Let's add more relevant info, like the fact that NAPI must already be
added before calling, calling context, etc.

> + */
> +int netif_queue_set_napi(unsigned int queue_index, enum netdev_queue_type type,
> +			 struct napi_struct *napi)

Let's make this helper void.
It will be a PITA for callers to handle any error this may return.

> +{
> +	struct net_device *dev = napi->dev;
> +	struct netdev_rx_queue *rxq;
> +	struct netdev_queue *txq;
> +
> +	if (!dev)
> +		return -EINVAL;

	if (WARN_ON_ONCE(...))
		return;

> +	default:
> +		return -EINVAL;
> +	}

same here

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue
  2023-10-06  9:14 ` [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue Amritha Nambiar
@ 2023-10-11  2:25   ` Jakub Kicinski
  2023-10-11 23:54     ` Nambiar, Amritha
  0 siblings, 1 reply; 24+ messages in thread
From: Jakub Kicinski @ 2023-10-11  2:25 UTC (permalink / raw)
  To: Amritha Nambiar; +Cc: netdev, sridhar.samudrala

On Fri, 06 Oct 2023 02:14:59 -0700 Amritha Nambiar wrote:
> +static int
> +netdev_nl_queue_fill_one(struct sk_buff *rsp, struct net_device *netdev,
> +			 u32 q_idx, u32 q_type, const struct genl_info *info)
> +{
> +	struct netdev_rx_queue *rxq;
> +	struct netdev_queue *txq;
> +	void *hdr;
> +
> +	hdr = genlmsg_iput(rsp, info);
> +	if (!hdr)
> +		return -EMSGSIZE;
> +
> +	if (nla_put_u32(rsp, NETDEV_A_QUEUE_QUEUE_ID, q_idx))
> +		goto nla_put_failure;
> +
> +	if (nla_put_u32(rsp, NETDEV_A_QUEUE_QUEUE_TYPE, q_type))
> +		goto nla_put_failure;
> +
> +	if (nla_put_u32(rsp, NETDEV_A_QUEUE_IFINDEX, netdev->ifindex))
> +		goto nla_put_failure;

You can combine these ifs in a single one using ||

> +	switch (q_type) {
> +	case NETDEV_QUEUE_TYPE_RX:
> +		rxq = __netif_get_rx_queue(netdev, q_idx);
> +		if (rxq->napi && nla_put_u32(rsp, NETDEV_A_QUEUE_NAPI_ID,

> +static int netdev_nl_queue_validate(struct net_device *netdev, u32 q_id,
> +				    u32 q_type)
> +{
> +	switch (q_type) {
> +	case NETDEV_QUEUE_TYPE_RX:
> +		if (q_id >= netdev->real_num_rx_queues)
> +			return -EINVAL;
> +		return 0;
> +	case NETDEV_QUEUE_TYPE_TX:
> +		if (q_id >= netdev->real_num_tx_queues)
> +			return -EINVAL;
> +		return 0;
> +	default:
> +		return -EOPNOTSUPP;

Doesn't the netlink policy prevent this already?

> +	}
> +}

>  int netdev_nl_queue_get_doit(struct sk_buff *skb, struct genl_info *info)
>  {
> -	return -EOPNOTSUPP;
> +	u32 q_id, q_type, ifindex;
> +	struct net_device *netdev;
> +	struct sk_buff *rsp;
> +	int err;
> +
> +	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_QUEUE_ID))
> +		return -EINVAL;
> +
> +	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_QUEUE_TYPE))
> +		return -EINVAL;
> +
> +	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_IFINDEX))
> +		return -EINVAL;

You can combine these checks in a single if using ||

> +	q_id = nla_get_u32(info->attrs[NETDEV_A_QUEUE_QUEUE_ID]);
> +
> +	q_type = nla_get_u32(info->attrs[NETDEV_A_QUEUE_QUEUE_TYPE]);
> +
> +	ifindex = nla_get_u32(info->attrs[NETDEV_A_QUEUE_IFINDEX]);

No need for the empty lines between these.

> +	rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
> +	if (!rsp)
> +		return -ENOMEM;
> +
> +	rtnl_lock();
> +
> +	netdev = __dev_get_by_index(genl_info_net(info), ifindex);
> +	if (netdev)
> +		err  = netdev_nl_queue_fill(rsp, netdev, q_id, q_type, info);

double space after =

> +	else
> +		err = -ENODEV;
> +
> +	rtnl_unlock();
> +
> +	if (err)
> +		goto err_free_msg;
> +
> +	return genlmsg_reply(rsp, info);
> +
> +err_free_msg:
> +	nlmsg_free(rsp);
> +	return err;
> +}
> +
> +static int
> +netdev_nl_queue_dump_one(struct net_device *netdev, struct sk_buff *rsp,
> +			 const struct genl_info *info, unsigned int *start_rx,
> +			 unsigned int *start_tx)
> +{

Hm. Not sure why you don't operate directly on ctx here.
Why pass the indexes by pointer individually?

> +	int err = 0;
> +	int i;
> +
> +	for (i = *start_rx; i < netdev->real_num_rx_queues;) {
> +		err = netdev_nl_queue_fill_one(rsp, netdev, i,
> +					       NETDEV_QUEUE_TYPE_RX, info);
> +		if (err)
> +			goto out_err;

return, no need to goto if all it does is returns

> +		*start_rx = i++;
> +	}
> +	for (i = *start_tx; i < netdev->real_num_tx_queues;) {
> +		err = netdev_nl_queue_fill_one(rsp, netdev, i,
> +					       NETDEV_QUEUE_TYPE_TX, info);
> +		if (err)
> +			goto out_err;
> +		*start_tx = i++;
> +	}
> +out_err:
> +	return err;
>  }
>  
>  int netdev_nl_queue_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
>  {
> -	return -EOPNOTSUPP;
> +	struct netdev_nl_dump_ctx *ctx = netdev_dump_ctx(cb);
> +	const struct genl_info *info = genl_info_dump(cb);
> +	struct net *net = sock_net(skb->sk);
> +	unsigned int rxq_idx = ctx->rxq_idx;
> +	unsigned int txq_idx = ctx->txq_idx;
> +	struct net_device *netdev;
> +	u32 ifindex = 0;
> +	int err = 0;
> +
> +	if (info->attrs[NETDEV_A_QUEUE_IFINDEX])
> +		ifindex = nla_get_u32(info->attrs[NETDEV_A_QUEUE_IFINDEX]);
> +
> +	rtnl_lock();
> +	if (ifindex) {
> +		netdev = __dev_get_by_index(net, ifindex);
> +		if (netdev)
> +			err = netdev_nl_queue_dump_one(netdev, skb, info,
> +						       &rxq_idx, &txq_idx);
> +		else
> +			err = -ENODEV;
> +	} else {
> +		for_each_netdev_dump(net, netdev, ctx->ifindex) {
> +			err = netdev_nl_queue_dump_one(netdev, skb, info,
> +						       &rxq_idx, &txq_idx);
> +

unnecessary new line

> +			if (err < 0)
> +				break;
> +			if (!err) {

it only returns 0 or negative errno, doesn't it?

> +				rxq_idx = 0;
> +				txq_idx = 0;
> +			}
> +		}
> +	}
> +	rtnl_unlock();
> +
> +	if (err != -EMSGSIZE)
> +		return err;
> +
> +	ctx->rxq_idx = rxq_idx;
> +	ctx->txq_idx = txq_idx;
> +	return skb->len;
>  }
>  
>  static int netdev_genl_netdevice_event(struct notifier_block *nb,
> 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 06/10] netdev-genl: Add netlink framework functions for napi
  2023-10-06  9:15 ` [net-next PATCH v4 06/10] netdev-genl: Add netlink framework functions for napi Amritha Nambiar
@ 2023-10-11  2:29   ` Jakub Kicinski
  2023-10-11 23:55     ` Nambiar, Amritha
  0 siblings, 1 reply; 24+ messages in thread
From: Jakub Kicinski @ 2023-10-11  2:29 UTC (permalink / raw)
  To: Amritha Nambiar; +Cc: netdev, sridhar.samudrala

On Fri, 06 Oct 2023 02:15:10 -0700 Amritha Nambiar wrote:
> Implement the netdev netlink framework functions for
> napi support. The netdev structure tracks all the napi
> instances and napi fields. The napi instances and associated
> parameters can be retrieved this way.
> 
> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
> Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
> ---
>  include/linux/netdevice.h |    2 +
>  net/core/dev.c            |    4 +-
>  net/core/netdev-genl.c    |  117 ++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 119 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 264ae0bdabe8..da211f4d81db 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -536,6 +536,8 @@ static inline bool napi_complete(struct napi_struct *n)
>  	return napi_complete_done(n, 0);
>  }
>  
> +struct napi_struct *napi_by_id(unsigned int napi_id);

this can go into net/core/dev.h ?

>  int dev_set_threaded(struct net_device *dev, bool threaded);
>  
>  /**

> @@ -6144,6 +6143,7 @@ static struct napi_struct *napi_by_id(unsigned int napi_id)
>  
>  	return NULL;
>  }
> +EXPORT_SYMBOL(napi_by_id);

Why is it exported? Exports are for use in modules.

>  int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info)
>  {
> -	return -EOPNOTSUPP;
> +	struct napi_struct *napi;
> +	struct sk_buff *rsp;
> +	u32 napi_id;
> +	int err;
> +
> +	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_NAPI_NAPI_ID))
> +		return -EINVAL;
> +
> +	napi_id = nla_get_u32(info->attrs[NETDEV_A_NAPI_NAPI_ID]);
> +
> +	rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
> +	if (!rsp)
> +		return -ENOMEM;
> +
> +	rcu_read_lock();
> +
> +	napi = napi_by_id(napi_id);
> +	if (napi)
> +		err  = netdev_nl_napi_fill_one(rsp, napi, info);

double space

> +	else
> +		err = -EINVAL;


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 01/10] netdev-genl: spec: Extend netdev netlink spec in YAML for queue
  2023-10-11  2:12   ` Jakub Kicinski
@ 2023-10-11 23:28     ` Nambiar, Amritha
  0 siblings, 0 replies; 24+ messages in thread
From: Nambiar, Amritha @ 2023-10-11 23:28 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, sridhar.samudrala

On 10/10/2023 7:12 PM, Jakub Kicinski wrote:
> On Fri, 06 Oct 2023 02:14:43 -0700 Amritha Nambiar wrote:
>> Add support in netlink spec(netdev.yaml) for queue information.
>> Add code generated from the spec.
>>
>> Note: The "queue-type" attribute currently takes values 0 and 1
>> for rx and tx queue type respectively. I haven't figured out the
>> ynl library changes to support string user input ("rx" and "tx")
>> to enum value conversion in the generated C code.
> 
> Let's leave the maxrate out of this version entirely, please.
> Otherwise looks good.

Okay, will remove maxrate in v5.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 02/10] net: Add queue and napi association
  2023-10-11  2:17   ` Jakub Kicinski
@ 2023-10-11 23:36     ` Nambiar, Amritha
  0 siblings, 0 replies; 24+ messages in thread
From: Nambiar, Amritha @ 2023-10-11 23:36 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, sridhar.samudrala

On 10/10/2023 7:17 PM, Jakub Kicinski wrote:
> On Fri, 06 Oct 2023 02:14:48 -0700 Amritha Nambiar wrote:
>>   #endif
>> +	/* NAPI instance for the queue */
>> +	struct napi_struct		*napi;
> 
> What's the protection on this field?
> Writers and readers must be under rtnl_lock?
> 

Yes, writers and readers must be under rtnl_lock. I will modify 
netif_queue_set_napi() for rtnl protection from writers. Readers are 
holding rtnl_lock.

>>   } ____cacheline_aligned_in_smp;
>>   
>>   /*
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index 606a366cc209..9b63a7b76c01 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -6394,6 +6394,40 @@ int dev_set_threaded(struct net_device *dev, bool threaded)
>>   }
>>   EXPORT_SYMBOL(dev_set_threaded);
>>   
>> +/**
>> + * netif_queue_set_napi - Associate queue with the napi
>> + * @queue_index: Index of queue
>> + * @type: queue type as RX or TX
>> + * @napi: NAPI context
>> + *
>> + * Set queue with its corresponding napi context
> 
> Let's add more relevant info, like the fact that NAPI must already be
> added before calling, calling context, etc.
> 

Okay, will fix in v5.

>> + */
>> +int netif_queue_set_napi(unsigned int queue_index, enum netdev_queue_type type,
>> +			 struct napi_struct *napi)
> 
> Let's make this helper void.
> It will be a PITA for callers to handle any error this may return.
> 

Okay, will make this a void function in v5.

>> +{
>> +	struct net_device *dev = napi->dev;
>> +	struct netdev_rx_queue *rxq;
>> +	struct netdev_queue *txq;
>> +
>> +	if (!dev)
>> +		return -EINVAL;
> 
> 	if (WARN_ON_ONCE(...))
> 		return;
> 
>> +	default:
>> +		return -EINVAL;
>> +	}
> 
> same here

Will fix in v5.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue
  2023-10-11  2:25   ` Jakub Kicinski
@ 2023-10-11 23:54     ` Nambiar, Amritha
  2023-10-12 23:48       ` Jakub Kicinski
  0 siblings, 1 reply; 24+ messages in thread
From: Nambiar, Amritha @ 2023-10-11 23:54 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, sridhar.samudrala



On 10/10/2023 7:25 PM, Jakub Kicinski wrote:
> On Fri, 06 Oct 2023 02:14:59 -0700 Amritha Nambiar wrote:
>> +static int
>> +netdev_nl_queue_fill_one(struct sk_buff *rsp, struct net_device *netdev,
>> +			 u32 q_idx, u32 q_type, const struct genl_info *info)
>> +{
>> +	struct netdev_rx_queue *rxq;
>> +	struct netdev_queue *txq;
>> +	void *hdr;
>> +
>> +	hdr = genlmsg_iput(rsp, info);
>> +	if (!hdr)
>> +		return -EMSGSIZE;
>> +
>> +	if (nla_put_u32(rsp, NETDEV_A_QUEUE_QUEUE_ID, q_idx))
>> +		goto nla_put_failure;
>> +
>> +	if (nla_put_u32(rsp, NETDEV_A_QUEUE_QUEUE_TYPE, q_type))
>> +		goto nla_put_failure;
>> +
>> +	if (nla_put_u32(rsp, NETDEV_A_QUEUE_IFINDEX, netdev->ifindex))
>> +		goto nla_put_failure;
> 
> You can combine these ifs in a single one using ||
> 
Okay, will fix in v5.

>> +	switch (q_type) {
>> +	case NETDEV_QUEUE_TYPE_RX:
>> +		rxq = __netif_get_rx_queue(netdev, q_idx);
>> +		if (rxq->napi && nla_put_u32(rsp, NETDEV_A_QUEUE_NAPI_ID,
> 
>> +static int netdev_nl_queue_validate(struct net_device *netdev, u32 q_id,
>> +				    u32 q_type)
>> +{
>> +	switch (q_type) {
>> +	case NETDEV_QUEUE_TYPE_RX:
>> +		if (q_id >= netdev->real_num_rx_queues)
>> +			return -EINVAL;
>> +		return 0;
>> +	case NETDEV_QUEUE_TYPE_TX:
>> +		if (q_id >= netdev->real_num_tx_queues)
>> +			return -EINVAL;
>> +		return 0;
>> +	default:
>> +		return -EOPNOTSUPP;
> 
> Doesn't the netlink policy prevent this already?

For this, should I be using "checks: max:" as an attribute property for 
the 'queue-id' attribute in the yaml. If so, not sure how I can give a 
custom value (not hard-coded) for max.
Or should I include a pre-doit hook.

> 
>> +	}
>> +}
> 
>>   int netdev_nl_queue_get_doit(struct sk_buff *skb, struct genl_info *info)
>>   {
>> -	return -EOPNOTSUPP;
>> +	u32 q_id, q_type, ifindex;
>> +	struct net_device *netdev;
>> +	struct sk_buff *rsp;
>> +	int err;
>> +
>> +	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_QUEUE_ID))
>> +		return -EINVAL;
>> +
>> +	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_QUEUE_TYPE))
>> +		return -EINVAL;
>> +
>> +	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_QUEUE_IFINDEX))
>> +		return -EINVAL;
> 
> You can combine these checks in a single if using ||

Will fix in v5.

> 
>> +	q_id = nla_get_u32(info->attrs[NETDEV_A_QUEUE_QUEUE_ID]);
>> +
>> +	q_type = nla_get_u32(info->attrs[NETDEV_A_QUEUE_QUEUE_TYPE]);
>> +
>> +	ifindex = nla_get_u32(info->attrs[NETDEV_A_QUEUE_IFINDEX]);
> 
> No need for the empty lines between these.

Will fix.

> 
>> +	rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
>> +	if (!rsp)
>> +		return -ENOMEM;
>> +
>> +	rtnl_lock();
>> +
>> +	netdev = __dev_get_by_index(genl_info_net(info), ifindex);
>> +	if (netdev)
>> +		err  = netdev_nl_queue_fill(rsp, netdev, q_id, q_type, info);
> 
> double space after =

Will fix.

> 
>> +	else
>> +		err = -ENODEV;
>> +
>> +	rtnl_unlock();
>> +
>> +	if (err)
>> +		goto err_free_msg;
>> +
>> +	return genlmsg_reply(rsp, info);
>> +
>> +err_free_msg:
>> +	nlmsg_free(rsp);
>> +	return err;
>> +}
>> +
>> +static int
>> +netdev_nl_queue_dump_one(struct net_device *netdev, struct sk_buff *rsp,
>> +			 const struct genl_info *info, unsigned int *start_rx,
>> +			 unsigned int *start_tx)
>> +{
> 
> Hm. Not sure why you don't operate directly on ctx here.
> Why pass the indexes by pointer individually?
> 

Makes sense. Will fix in v5.

>> +	int err = 0;
>> +	int i;
>> +
>> +	for (i = *start_rx; i < netdev->real_num_rx_queues;) {
>> +		err = netdev_nl_queue_fill_one(rsp, netdev, i,
>> +					       NETDEV_QUEUE_TYPE_RX, info);
>> +		if (err)
>> +			goto out_err;
> 
> return, no need to goto if all it does is returns

Will fix.

> 
>> +		*start_rx = i++;
>> +	}
>> +	for (i = *start_tx; i < netdev->real_num_tx_queues;) {
>> +		err = netdev_nl_queue_fill_one(rsp, netdev, i,
>> +					       NETDEV_QUEUE_TYPE_TX, info);
>> +		if (err)
>> +			goto out_err;
>> +		*start_tx = i++;
>> +	}
>> +out_err:
>> +	return err;
>>   }
>>   
>>   int netdev_nl_queue_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
>>   {
>> -	return -EOPNOTSUPP;
>> +	struct netdev_nl_dump_ctx *ctx = netdev_dump_ctx(cb);
>> +	const struct genl_info *info = genl_info_dump(cb);
>> +	struct net *net = sock_net(skb->sk);
>> +	unsigned int rxq_idx = ctx->rxq_idx;
>> +	unsigned int txq_idx = ctx->txq_idx;
>> +	struct net_device *netdev;
>> +	u32 ifindex = 0;
>> +	int err = 0;
>> +
>> +	if (info->attrs[NETDEV_A_QUEUE_IFINDEX])
>> +		ifindex = nla_get_u32(info->attrs[NETDEV_A_QUEUE_IFINDEX]);
>> +
>> +	rtnl_lock();
>> +	if (ifindex) {
>> +		netdev = __dev_get_by_index(net, ifindex);
>> +		if (netdev)
>> +			err = netdev_nl_queue_dump_one(netdev, skb, info,
>> +						       &rxq_idx, &txq_idx);
>> +		else
>> +			err = -ENODEV;
>> +	} else {
>> +		for_each_netdev_dump(net, netdev, ctx->ifindex) {
>> +			err = netdev_nl_queue_dump_one(netdev, skb, info,
>> +						       &rxq_idx, &txq_idx);
>> +
> 
> unnecessary new line

Will fix.

> 
>> +			if (err < 0)
>> +				break;
>> +			if (!err) {
> 
> it only returns 0 or negative errno, doesn't it?
> 
Will fix in v5.

>> +				rxq_idx = 0;
>> +				txq_idx = 0;
>> +			}
>> +		}
>> +	}
>> +	rtnl_unlock();
>> +
>> +	if (err != -EMSGSIZE)
>> +		return err;
>> +
>> +	ctx->rxq_idx = rxq_idx;
>> +	ctx->txq_idx = txq_idx;
>> +	return skb->len;
>>   }
>>   
>>   static int netdev_genl_netdevice_event(struct notifier_block *nb,
>>
> 
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 06/10] netdev-genl: Add netlink framework functions for napi
  2023-10-11  2:29   ` Jakub Kicinski
@ 2023-10-11 23:55     ` Nambiar, Amritha
  0 siblings, 0 replies; 24+ messages in thread
From: Nambiar, Amritha @ 2023-10-11 23:55 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, sridhar.samudrala

On 10/10/2023 7:29 PM, Jakub Kicinski wrote:
> On Fri, 06 Oct 2023 02:15:10 -0700 Amritha Nambiar wrote:
>> Implement the netdev netlink framework functions for
>> napi support. The netdev structure tracks all the napi
>> instances and napi fields. The napi instances and associated
>> parameters can be retrieved this way.
>>
>> Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com>
>> Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
>> ---
>>   include/linux/netdevice.h |    2 +
>>   net/core/dev.c            |    4 +-
>>   net/core/netdev-genl.c    |  117 ++++++++++++++++++++++++++++++++++++++++++++-
>>   3 files changed, 119 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>> index 264ae0bdabe8..da211f4d81db 100644
>> --- a/include/linux/netdevice.h
>> +++ b/include/linux/netdevice.h
>> @@ -536,6 +536,8 @@ static inline bool napi_complete(struct napi_struct *n)
>>   	return napi_complete_done(n, 0);
>>   }
>>   
>> +struct napi_struct *napi_by_id(unsigned int napi_id);
> 
> this can go into net/core/dev.h ?
> 

Okay, will move this to net/core/dev.h

>>   int dev_set_threaded(struct net_device *dev, bool threaded);
>>   
>>   /**
> 
>> @@ -6144,6 +6143,7 @@ static struct napi_struct *napi_by_id(unsigned int napi_id)
>>   
>>   	return NULL;
>>   }
>> +EXPORT_SYMBOL(napi_by_id);
> 
> Why is it exported? Exports are for use in modules.
> 

Will fix in v5.

>>   int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info)
>>   {
>> -	return -EOPNOTSUPP;
>> +	struct napi_struct *napi;
>> +	struct sk_buff *rsp;
>> +	u32 napi_id;
>> +	int err;
>> +
>> +	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_NAPI_NAPI_ID))
>> +		return -EINVAL;
>> +
>> +	napi_id = nla_get_u32(info->attrs[NETDEV_A_NAPI_NAPI_ID]);
>> +
>> +	rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
>> +	if (!rsp)
>> +		return -ENOMEM;
>> +
>> +	rcu_read_lock();
>> +
>> +	napi = napi_by_id(napi_id);
>> +	if (napi)
>> +		err  = netdev_nl_napi_fill_one(rsp, napi, info);
> 
> double space

Will fix.

> 
>> +	else
>> +		err = -EINVAL;
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue
  2023-10-11 23:54     ` Nambiar, Amritha
@ 2023-10-12 23:48       ` Jakub Kicinski
  2023-10-13  0:24         ` Nambiar, Amritha
  0 siblings, 1 reply; 24+ messages in thread
From: Jakub Kicinski @ 2023-10-12 23:48 UTC (permalink / raw)
  To: Nambiar, Amritha; +Cc: netdev, sridhar.samudrala

On Wed, 11 Oct 2023 16:54:00 -0700 Nambiar, Amritha wrote:
> >> +static int netdev_nl_queue_validate(struct net_device *netdev, u32 q_id,
> >> +				    u32 q_type)
> >> +{
> >> +	switch (q_type) {
> >> +	case NETDEV_QUEUE_TYPE_RX:
> >> +		if (q_id >= netdev->real_num_rx_queues)
> >> +			return -EINVAL;
> >> +		return 0;
> >> +	case NETDEV_QUEUE_TYPE_TX:
> >> +		if (q_id >= netdev->real_num_tx_queues)
> >> +			return -EINVAL;
> >> +		return 0;
> >> +	default:
> >> +		return -EOPNOTSUPP;  
> > 
> > Doesn't the netlink policy prevent this already?  
> 
> For this, should I be using "checks: max:" as an attribute property for 
> the 'queue-id' attribute in the yaml. If so, not sure how I can give a 
> custom value (not hard-coded) for max.
> Or should I include a pre-doit hook.

Weird, I was convinced that if you specify enum by default the code gen
will automatically generate the range check to make sure that the value
is within the enum..

Looks like it does, this is the policy, right?

+static const struct nla_policy netdev_queue_get_do_nl_policy[NETDEV_A_QUEUE_QUEUE_TYPE + 1] = {
+	[NETDEV_A_QUEUE_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1),
+	[NETDEV_A_QUEUE_QUEUE_TYPE] = NLA_POLICY_MAX(NLA_U32, 1),
 	                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue
  2023-10-12 23:48       ` Jakub Kicinski
@ 2023-10-13  0:24         ` Nambiar, Amritha
  2023-10-13  0:36           ` Jakub Kicinski
  0 siblings, 1 reply; 24+ messages in thread
From: Nambiar, Amritha @ 2023-10-13  0:24 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, sridhar.samudrala

On 10/12/2023 4:48 PM, Jakub Kicinski wrote:
> On Wed, 11 Oct 2023 16:54:00 -0700 Nambiar, Amritha wrote:
>>>> +static int netdev_nl_queue_validate(struct net_device *netdev, u32 q_id,
>>>> +				    u32 q_type)
>>>> +{
>>>> +	switch (q_type) {
>>>> +	case NETDEV_QUEUE_TYPE_RX:
>>>> +		if (q_id >= netdev->real_num_rx_queues)
>>>> +			return -EINVAL;
>>>> +		return 0;
>>>> +	case NETDEV_QUEUE_TYPE_TX:
>>>> +		if (q_id >= netdev->real_num_tx_queues)
>>>> +			return -EINVAL;
>>>> +		return 0;
>>>> +	default:
>>>> +		return -EOPNOTSUPP;
>>>
>>> Doesn't the netlink policy prevent this already?
>>
>> For this, should I be using "checks: max:" as an attribute property for
>> the 'queue-id' attribute in the yaml. If so, not sure how I can give a
>> custom value (not hard-coded) for max.
>> Or should I include a pre-doit hook.
> 
> Weird, I was convinced that if you specify enum by default the code gen
> will automatically generate the range check to make sure that the value
> is within the enum..
> 
> Looks like it does, this is the policy, right?
> 
> +static const struct nla_policy netdev_queue_get_do_nl_policy[NETDEV_A_QUEUE_QUEUE_TYPE + 1] = {
> +	[NETDEV_A_QUEUE_IFINDEX] = NLA_POLICY_MIN(NLA_U32, 1),
> +	[NETDEV_A_QUEUE_QUEUE_TYPE] = NLA_POLICY_MAX(NLA_U32, 1),
>   	                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^

Yes, this is the policy. This policy does validate that the max value 
for 'queue-type' is within the enum range.

I was thinking your review comment was for the entire 
'netdev_nl_queue_validate' function (i.e. if the max queue-id validation 
can be handled in the policy as a range with max value for queue-id, and 
since max queue-id was not a constant, but varies within the kernel, ex: 
netdev->real_num_rx_queues, I was unsure of it...). So, another option I 
could come up with for the validation was a 'pre_doit' hook instead of 
netdev_nl_queue_validate().

If your comment referred to the enum queue-type range alone, I see, 
since the policy handles the max check for queue-type, I can remove the 
default case returning EOPNOTSUPP. Correct me if I'm wrong.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue
  2023-10-13  0:24         ` Nambiar, Amritha
@ 2023-10-13  0:36           ` Jakub Kicinski
  2023-10-13  0:40             ` Nambiar, Amritha
  2023-10-13  0:44             ` Jakub Kicinski
  0 siblings, 2 replies; 24+ messages in thread
From: Jakub Kicinski @ 2023-10-13  0:36 UTC (permalink / raw)
  To: Nambiar, Amritha; +Cc: netdev, sridhar.samudrala

On Thu, 12 Oct 2023 17:24:41 -0700 Nambiar, Amritha wrote:
> I was thinking your review comment was for the entire 
> 'netdev_nl_queue_validate' function (i.e. if the max queue-id validation 
> can be handled in the policy as a range with max value for queue-id, and 
> since max queue-id was not a constant, but varies within the kernel, ex: 
> netdev->real_num_rx_queues, I was unsure of it...). So, another option I 
> could come up with for the validation was a 'pre_doit' hook instead of 
> netdev_nl_queue_validate().

real_num can change if we're not holding rtnl_lock, and we can't hold
the lock in pre :(

> If your comment referred to the enum queue-type range alone, I see, 
> since the policy handles the max check for queue-type, I can remove the 
> default case returning EOPNOTSUPP. Correct me if I'm wrong.

Yup! I only meant the type, you can trust netlink to validate the type.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue
  2023-10-13  0:36           ` Jakub Kicinski
@ 2023-10-13  0:40             ` Nambiar, Amritha
  2023-10-13  0:44             ` Jakub Kicinski
  1 sibling, 0 replies; 24+ messages in thread
From: Nambiar, Amritha @ 2023-10-13  0:40 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, sridhar.samudrala

On 10/12/2023 5:36 PM, Jakub Kicinski wrote:
> On Thu, 12 Oct 2023 17:24:41 -0700 Nambiar, Amritha wrote:
>> I was thinking your review comment was for the entire
>> 'netdev_nl_queue_validate' function (i.e. if the max queue-id validation
>> can be handled in the policy as a range with max value for queue-id, and
>> since max queue-id was not a constant, but varies within the kernel, ex:
>> netdev->real_num_rx_queues, I was unsure of it...). So, another option I
>> could come up with for the validation was a 'pre_doit' hook instead of
>> netdev_nl_queue_validate().
> 
> real_num can change if we're not holding rtnl_lock, and we can't hold
> the lock in pre :(
> 
I see.

>> If your comment referred to the enum queue-type range alone, I see,
>> since the policy handles the max check for queue-type, I can remove the
>> default case returning EOPNOTSUPP. Correct me if I'm wrong.
> 
> Yup! I only meant the type, you can trust netlink to validate the type.

Got it. Thanks!

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue
  2023-10-13  0:36           ` Jakub Kicinski
  2023-10-13  0:40             ` Nambiar, Amritha
@ 2023-10-13  0:44             ` Jakub Kicinski
  1 sibling, 0 replies; 24+ messages in thread
From: Jakub Kicinski @ 2023-10-13  0:44 UTC (permalink / raw)
  To: Nambiar, Amritha; +Cc: netdev, sridhar.samudrala

On Thu, 12 Oct 2023 17:36:36 -0700 Jakub Kicinski wrote:
> we can't hold the lock in pre :(

To be clear - I meant to say that for dumps we can't hold the lock
across all the callbacks, for do it would technically be fine.
But I don't think that it's better.

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2023-10-13  0:44 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-06  9:14 [net-next PATCH v4 00/10] Introduce queue and NAPI support in netdev-genl (Was: Introduce NAPI queues support) Amritha Nambiar
2023-10-06  9:14 ` [net-next PATCH v4 01/10] netdev-genl: spec: Extend netdev netlink spec in YAML for queue Amritha Nambiar
2023-10-11  2:12   ` Jakub Kicinski
2023-10-11 23:28     ` Nambiar, Amritha
2023-10-06  9:14 ` [net-next PATCH v4 02/10] net: Add queue and napi association Amritha Nambiar
2023-10-11  2:17   ` Jakub Kicinski
2023-10-11 23:36     ` Nambiar, Amritha
2023-10-06  9:14 ` [net-next PATCH v4 03/10] ice: Add support in the driver for associating queue with napi Amritha Nambiar
2023-10-06  9:14 ` [net-next PATCH v4 04/10] netdev-genl: Add netlink framework functions for queue Amritha Nambiar
2023-10-11  2:25   ` Jakub Kicinski
2023-10-11 23:54     ` Nambiar, Amritha
2023-10-12 23:48       ` Jakub Kicinski
2023-10-13  0:24         ` Nambiar, Amritha
2023-10-13  0:36           ` Jakub Kicinski
2023-10-13  0:40             ` Nambiar, Amritha
2023-10-13  0:44             ` Jakub Kicinski
2023-10-06  9:15 ` [net-next PATCH v4 05/10] netdev-genl: spec: Extend netdev netlink spec in YAML for NAPI Amritha Nambiar
2023-10-06  9:15 ` [net-next PATCH v4 06/10] netdev-genl: Add netlink framework functions for napi Amritha Nambiar
2023-10-11  2:29   ` Jakub Kicinski
2023-10-11 23:55     ` Nambiar, Amritha
2023-10-06  9:15 ` [net-next PATCH v4 07/10] netdev-genl: spec: Add irq in netdev netlink YAML spec Amritha Nambiar
2023-10-06  9:15 ` [net-next PATCH v4 08/10] net: Add NAPI IRQ support Amritha Nambiar
2023-10-06  9:15 ` [net-next PATCH v4 09/10] netdev-genl: spec: Add PID in netdev netlink YAML spec Amritha Nambiar
2023-10-06  9:15 ` [net-next PATCH v4 10/10] netdev-genl: Add PID for the NAPI thread Amritha Nambiar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).