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 <jdam...@fastly.com>
---
 .../testing/selftests/drivers/net/.gitignore  |  1 +
 tools/testing/selftests/drivers/net/Makefile  |  6 +-
 .../testing/selftests/drivers/net/napi_id.py  | 23 +++++
 .../selftests/drivers/net/napi_id_helper.c    | 83 +++++++++++++++++++
 4 files changed, 112 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..356bac46ba04
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/napi_id.py
@@ -0,0 +1,23 @@
+#!/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()
+    listen_cmd = f"{cfg.test_dir}/napi_id_helper {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


Reply via email to