Commit 2677010e authored by Samiullah Khawaja's avatar Samiullah Khawaja Committed by Jakub Kicinski
Browse files

Add support to set NAPI threaded for individual NAPI



A net device has a threaded sysctl that can be used to enable threaded
NAPI polling on all of the NAPI contexts under that device. Allow
enabling threaded NAPI polling at individual NAPI level using netlink.

Extend the netlink operation `napi-set` and allow setting the threaded
attribute of a NAPI. This will enable the threaded polling on a NAPI
context.

Add a test in `nl_netdev.py` that verifies various cases of threaded
NAPI being set at NAPI and at device level.

Tested
 ./tools/testing/selftests/net/nl_netdev.py
 TAP version 13
 1..7
 ok 1 nl_netdev.empty_check
 ok 2 nl_netdev.lo_check
 ok 3 nl_netdev.page_pool_check
 ok 4 nl_netdev.napi_list_check
 ok 5 nl_netdev.dev_set_threaded
 ok 6 nl_netdev.napi_set_threaded
 ok 7 nl_netdev.nsim_rxq_reset_down
 # Totals: pass:7 fail:0 xfail:0 xpass:0 skip:0 error:0

Signed-off-by: default avatarSamiullah Khawaja <skhawaja@google.com>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20250710211203.3979655-1-skhawaja@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a44312d5
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -283,6 +283,14 @@ attribute-sets:
        doc: The timeout, in nanoseconds, of how long to suspend irq
             processing, if event polling finds events
        type: uint
      -
        name: threaded
        doc: Whether the NAPI is configured to operate in threaded polling
             mode. If this is set to 1 then the NAPI context operates in
             threaded polling mode.
        type: uint
        checks:
          max: 1
  -
    name: xsk-info
    attributes: []
@@ -694,6 +702,7 @@ operations:
            - defer-hard-irqs
            - gro-flush-timeout
            - irq-suspend-timeout
            - threaded
      dump:
        request:
          attributes:
@@ -746,6 +755,7 @@ operations:
            - defer-hard-irqs
            - gro-flush-timeout
            - irq-suspend-timeout
            - threaded
    -
      name: bind-tx
      doc: Bind dmabuf to netdev for TX
+8 −1
Original line number Diff line number Diff line
@@ -444,7 +444,14 @@ dependent). The NAPI instance IDs will be assigned in the opposite
order than the process IDs of the kernel threads.

Threaded NAPI is controlled by writing 0/1 to the ``threaded`` file in
netdev's sysfs directory.
netdev's sysfs directory. It can also be enabled for a specific NAPI using
netlink interface.

For example, using the script:

.. code-block:: bash

  $ ynl --family netdev --do napi-set --json='{"id": 66, "threaded": 1}'

.. rubric:: Footnotes

+1 −0
Original line number Diff line number Diff line
@@ -369,6 +369,7 @@ struct napi_config {
	u64 irq_suspend_timeout;
	u32 defer_hard_irqs;
	cpumask_t affinity_mask;
	bool threaded;
	unsigned int napi_id;
};

+1 −0
Original line number Diff line number Diff line
@@ -134,6 +134,7 @@ enum {
	NETDEV_A_NAPI_DEFER_HARD_IRQS,
	NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT,
	NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT,
	NETDEV_A_NAPI_THREADED,

	__NETDEV_A_NAPI_MAX,
	NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)
+27 −3
Original line number Diff line number Diff line
@@ -6961,6 +6961,31 @@ static void napi_stop_kthread(struct napi_struct *napi)
	napi->thread = NULL;
}

int napi_set_threaded(struct napi_struct *napi, bool threaded)
{
	if (threaded) {
		if (!napi->thread) {
			int err = napi_kthread_create(napi);

			if (err)
				return err;
		}
	}

	if (napi->config)
		napi->config->threaded = threaded;

	if (!threaded && napi->thread) {
		napi_stop_kthread(napi);
	} else {
		/* Make sure kthread is created before THREADED bit is set. */
		smp_mb__before_atomic();
		assign_bit(NAPI_STATE_THREADED, &napi->state, threaded);
	}

	return 0;
}

int dev_set_threaded(struct net_device *dev, bool threaded)
{
	struct napi_struct *napi;
@@ -6968,9 +6993,6 @@ int dev_set_threaded(struct net_device *dev, bool threaded)

	netdev_assert_locked_or_invisible(dev);

	if (dev->threaded == threaded)
		return 0;

	if (threaded) {
		list_for_each_entry(napi, &dev->napi_list, dev_list) {
			if (!napi->thread) {
@@ -7221,6 +7243,8 @@ static void napi_restore_config(struct napi_struct *n)
		napi_hash_add(n);
		n->config->napi_id = n->napi_id;
	}

	WARN_ON_ONCE(napi_set_threaded(n, n->config->threaded));
}

static void napi_save_config(struct napi_struct *n)
Loading