* [PATCH net-next v3 1/3] netdevsim: Mark NAPI ID on skb in nsim_rcv
2025-04-18 1:37 [PATCH net-next v3 0/3] Fix netdevim to correctly mark NAPI IDs Joe Damato
@ 2025-04-18 1:37 ` Joe Damato
2025-04-18 1:37 ` [PATCH net-next v3 2/3] selftests: drv-net: Factor out ksft C helpers Joe Damato
2025-04-18 1:37 ` [PATCH net-next v3 3/3] selftests: drv-net: Test that NAPI ID is non-zero Joe Damato
2 siblings, 0 replies; 8+ messages in thread
From: Joe Damato @ 2025-04-18 1:37 UTC (permalink / raw)
To: netdev
Cc: kuba, pabeni, shaw.leon, Joe Damato, Andrew Lunn, David S. Miller,
Eric Dumazet, open list
Previously, nsim_rcv was not marking the NAPI ID on the skb, leading to
applications seeing a napi ID of 0 when using SO_INCOMING_NAPI_ID.
To add to the userland confusion, netlink appears to correctly report
the NAPI IDs for netdevsim queues but the resulting file descriptor from
a call to accept() was reporting a NAPI ID of 0.
Signed-off-by: Joe Damato <jdamato@fastly.com>
---
drivers/net/netdevsim/netdev.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 0e0321a7ddd7..2aa999345fe1 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -29,6 +29,7 @@
#include <net/pkt_cls.h>
#include <net/rtnetlink.h>
#include <net/udp_tunnel.h>
+#include <net/busy_poll.h>
#include "netdevsim.h"
@@ -357,6 +358,7 @@ static int nsim_rcv(struct nsim_rq *rq, int budget)
break;
skb = skb_dequeue(&rq->skb_queue);
+ skb_mark_napi_id(skb, &rq->napi);
netif_receive_skb(skb);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next v3 2/3] selftests: drv-net: Factor out ksft C helpers
2025-04-18 1:37 [PATCH net-next v3 0/3] Fix netdevim to correctly mark NAPI IDs Joe Damato
2025-04-18 1:37 ` [PATCH net-next v3 1/3] netdevsim: Mark NAPI ID on skb in nsim_rcv Joe Damato
@ 2025-04-18 1:37 ` Joe Damato
2025-04-23 23:15 ` Jakub Kicinski
2025-04-18 1:37 ` [PATCH net-next v3 3/3] selftests: drv-net: Test that NAPI ID is non-zero Joe Damato
2 siblings, 1 reply; 8+ messages in thread
From: Joe Damato @ 2025-04-18 1:37 UTC (permalink / raw)
To: netdev
Cc: kuba, pabeni, shaw.leon, Joe Damato, Andrew Lunn, David S. Miller,
Eric Dumazet, Shuah Khan, Alexei Starovoitov, Daniel Borkmann,
Jesper Dangaard Brouer, John Fastabend, open list,
open list:KERNEL SELFTEST FRAMEWORK,
open list:XDP (eXpress Data Path):Keyword:(?:b|_)xdp(?:b|_)
Factor ksft C helpers to a header so they can be used by other C-based
tests.
Signed-off-by: Joe Damato <jdamato@fastly.com>
---
tools/testing/selftests/drivers/net/ksft.h | 56 +++++++++++++++++++
.../selftests/drivers/net/xdp_helper.c | 49 +---------------
2 files changed, 58 insertions(+), 47 deletions(-)
create mode 100644 tools/testing/selftests/drivers/net/ksft.h
diff --git a/tools/testing/selftests/drivers/net/ksft.h b/tools/testing/selftests/drivers/net/ksft.h
new file mode 100644
index 000000000000..3fd084006a16
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/ksft.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#if !defined(__KSFT_H__)
+#define __KSFT_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void ksft_ready(void)
+{
+ const char msg[7] = "ready\n";
+ char *env_str;
+ int fd;
+
+ env_str = getenv("KSFT_READY_FD");
+ if (env_str) {
+ fd = atoi(env_str);
+ if (!fd) {
+ fprintf(stderr, "invalid KSFT_READY_FD = '%s'\n",
+ env_str);
+ return;
+ }
+ } else {
+ fd = STDOUT_FILENO;
+ }
+
+ write(fd, msg, sizeof(msg));
+ if (fd != STDOUT_FILENO)
+ close(fd);
+}
+
+static void ksft_wait(void)
+{
+ char *env_str;
+ char byte;
+ int fd;
+
+ env_str = getenv("KSFT_WAIT_FD");
+ if (env_str) {
+ fd = atoi(env_str);
+ if (!fd) {
+ fprintf(stderr, "invalid KSFT_WAIT_FD = '%s'\n",
+ env_str);
+ return;
+ }
+ } else {
+ /* Not running in KSFT env, wait for input from STDIN instead */
+ fd = STDIN_FILENO;
+ }
+
+ read(fd, &byte, sizeof(byte));
+ if (fd != STDIN_FILENO)
+ close(fd);
+}
+
+#endif
diff --git a/tools/testing/selftests/drivers/net/xdp_helper.c b/tools/testing/selftests/drivers/net/xdp_helper.c
index aeed25914104..d5bb8ac33efa 100644
--- a/tools/testing/selftests/drivers/net/xdp_helper.c
+++ b/tools/testing/selftests/drivers/net/xdp_helper.c
@@ -11,56 +11,11 @@
#include <net/if.h>
#include <inttypes.h>
+#include "ksft.h"
+
#define UMEM_SZ (1U << 16)
#define NUM_DESC (UMEM_SZ / 2048)
-/* Move this to a common header when reused! */
-static void ksft_ready(void)
-{
- const char msg[7] = "ready\n";
- char *env_str;
- int fd;
-
- env_str = getenv("KSFT_READY_FD");
- if (env_str) {
- fd = atoi(env_str);
- if (!fd) {
- fprintf(stderr, "invalid KSFT_READY_FD = '%s'\n",
- env_str);
- return;
- }
- } else {
- fd = STDOUT_FILENO;
- }
-
- write(fd, msg, sizeof(msg));
- if (fd != STDOUT_FILENO)
- close(fd);
-}
-
-static void ksft_wait(void)
-{
- char *env_str;
- char byte;
- int fd;
-
- env_str = getenv("KSFT_WAIT_FD");
- if (env_str) {
- fd = atoi(env_str);
- if (!fd) {
- fprintf(stderr, "invalid KSFT_WAIT_FD = '%s'\n",
- env_str);
- return;
- }
- } else {
- /* Not running in KSFT env, wait for input from STDIN instead */
- fd = STDIN_FILENO;
- }
-
- read(fd, &byte, sizeof(byte));
- if (fd != STDIN_FILENO)
- close(fd);
-}
/* this is a simple helper program that creates an XDP socket and does the
* minimum necessary to get bind() to succeed.
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next v3 3/3] selftests: drv-net: Test that NAPI ID is non-zero
2025-04-18 1:37 [PATCH net-next v3 0/3] Fix netdevim to correctly mark NAPI IDs Joe Damato
2025-04-18 1:37 ` [PATCH net-next v3 1/3] netdevsim: Mark NAPI ID on skb in nsim_rcv Joe Damato
2025-04-18 1:37 ` [PATCH net-next v3 2/3] selftests: drv-net: Factor out ksft C helpers Joe Damato
@ 2025-04-18 1:37 ` Joe Damato
2025-04-23 23:16 ` Jakub Kicinski
2 siblings, 1 reply; 8+ messages in thread
From: Joe Damato @ 2025-04-18 1:37 UTC (permalink / raw)
To: netdev
Cc: kuba, pabeni, shaw.leon, Joe Damato, Andrew Lunn, David S. Miller,
Eric Dumazet, Shuah Khan, Alexei Starovoitov, Daniel Borkmann,
Jesper Dangaard Brouer, John Fastabend, open list,
open list:KERNEL SELFTEST FRAMEWORK,
open list:XDP (eXpress Data Path):Keyword:(?:b|_)xdp(?:b|_)
Test that the SO_INCOMING_NAPI_ID of a network file descriptor is
non-zero. This ensures that either the core networking stack or, in some
cases like netdevsim, the driver correctly sets the NAPI ID.
Signed-off-by: Joe Damato <jdamato@fastly.com>
---
.../testing/selftests/drivers/net/.gitignore | 1 +
tools/testing/selftests/drivers/net/Makefile | 6 +-
.../testing/selftests/drivers/net/napi_id.py | 24 ++++++
.../selftests/drivers/net/napi_id_helper.c | 83 +++++++++++++++++++
4 files changed, 113 insertions(+), 1 deletion(-)
create mode 100755 tools/testing/selftests/drivers/net/napi_id.py
create mode 100644 tools/testing/selftests/drivers/net/napi_id_helper.c
diff --git a/tools/testing/selftests/drivers/net/.gitignore b/tools/testing/selftests/drivers/net/.gitignore
index ec746f374e85..72d2124fd513 100644
--- a/tools/testing/selftests/drivers/net/.gitignore
+++ b/tools/testing/selftests/drivers/net/.gitignore
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0-only
+napi_id_helper
xdp_helper
diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
index 0c95bd944d56..47247c2ef948 100644
--- a/tools/testing/selftests/drivers/net/Makefile
+++ b/tools/testing/selftests/drivers/net/Makefile
@@ -6,9 +6,13 @@ TEST_INCLUDES := $(wildcard lib/py/*.py) \
../../net/net_helper.sh \
../../net/lib.sh \
-TEST_GEN_FILES := xdp_helper
+TEST_GEN_FILES := \
+ napi_id_helper \
+ xdp_helper \
+# end of TEST_GEN_FILES
TEST_PROGS := \
+ napi_id.py \
netcons_basic.sh \
netcons_fragmented_msg.sh \
netcons_overflow.sh \
diff --git a/tools/testing/selftests/drivers/net/napi_id.py b/tools/testing/selftests/drivers/net/napi_id.py
new file mode 100755
index 000000000000..54e51633a70a
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/napi_id.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+from lib.py import ksft_run, ksft_exit
+from lib.py import ksft_eq, NetDrvEpEnv
+from lib.py import bkg, cmd, rand_port, NetNSEnter
+
+def test_napi_id(cfg) -> None:
+ port = rand_port()
+ bin_remote = cfg.remote.deploy(cfg.test_dir / "napi_id_helper")
+ listen_cmd = f"{bin_remote} {cfg.addr_v['4']} {port}"
+
+ with bkg(listen_cmd, ksft_wait=3) as server:
+ cmd(f"echo a | socat - TCP:{cfg.addr_v['4']}:{port}", host=cfg.remote, shell=True)
+
+ ksft_eq(0, server.ret)
+
+def main() -> None:
+ with NetDrvEpEnv(__file__) as cfg:
+ ksft_run([test_napi_id], args=(cfg,))
+ ksft_exit()
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/testing/selftests/drivers/net/napi_id_helper.c b/tools/testing/selftests/drivers/net/napi_id_helper.c
new file mode 100644
index 000000000000..7e8e7d373b61
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/napi_id_helper.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include "ksft.h"
+
+int main(int argc, char *argv[])
+{
+ struct sockaddr_in address;
+ unsigned int napi_id;
+ unsigned int port;
+ socklen_t optlen;
+ char buf[1024];
+ int opt = 1;
+ int server;
+ int client;
+ int ret;
+
+ server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (server < 0) {
+ perror("socket creation failed");
+ if (errno == EAFNOSUPPORT)
+ return -1;
+ return 1;
+ }
+
+ port = atoi(argv[2]);
+
+ if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
+ perror("setsockopt");
+ return 1;
+ }
+
+ address.sin_family = AF_INET;
+ inet_pton(AF_INET, argv[1], &address.sin_addr);
+ address.sin_port = htons(port);
+
+ if (bind(server, (struct sockaddr *)&address, sizeof(address)) < 0) {
+ perror("bind failed");
+ return 1;
+ }
+
+ if (listen(server, 1) < 0) {
+ perror("listen");
+ return 1;
+ }
+
+ ksft_ready();
+
+ client = accept(server, NULL, 0);
+ if (client < 0) {
+ perror("accept");
+ return 1;
+ }
+
+ optlen = sizeof(napi_id);
+ ret = getsockopt(client, SOL_SOCKET, SO_INCOMING_NAPI_ID, &napi_id,
+ &optlen);
+ if (ret != 0) {
+ perror("getsockopt");
+ return 1;
+ }
+
+ read(client, buf, 1024);
+
+ ksft_wait();
+
+ if (napi_id == 0) {
+ fprintf(stderr, "napi ID is 0\n");
+ return 1;
+ }
+
+ close(client);
+ close(server);
+
+ return 0;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread