Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'fix-netdevim-to-correctly-mark-napi-ids'

Joe Damato says:

====================
Fix netdevim to correctly mark NAPI IDs

This series fixes netdevsim to correctly set the NAPI ID on the skb.
This is helpful for writing tests around features that use
SO_INCOMING_NAPI_ID.

In addition to the netdevsim fix in patch 1, patches 2 & 3 do some self
test refactoring and add a test for NAPI IDs. The test itself (patch 3)
introduces a C helper because apparently python doesn't have
socket.SO_INCOMING_NAPI_ID.

v3: https://lore.kernel.org/20250418013719.12094-1-jdamato@fastly.com
v2: https://lore.kernel.org/20250417013301.39228-1-jdamato@fastly.com
rfcv1: https://lore.kernel.org/20250329000030.39543-1-jdamato@fastly.com
====================

Link: https://patch.msgid.link/20250424002746.16891-1-jdamato@fastly.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+172 -48
+2
drivers/net/netdevsim/netdev.c
··· 29 29 #include <net/pkt_cls.h> 30 30 #include <net/rtnetlink.h> 31 31 #include <net/udp_tunnel.h> 32 + #include <net/busy_poll.h> 32 33 33 34 #include "netdevsim.h" 34 35 ··· 358 357 break; 359 358 360 359 skb = skb_dequeue(&rq->skb_queue); 360 + skb_mark_napi_id(skb, &rq->napi); 361 361 netif_receive_skb(skb); 362 362 } 363 363
+1
tools/testing/selftests/drivers/net/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 + napi_id_helper 2 3 xdp_helper
+5 -1
tools/testing/selftests/drivers/net/Makefile
··· 6 6 ../../net/net_helper.sh \ 7 7 ../../net/lib.sh \ 8 8 9 - TEST_GEN_FILES := xdp_helper 9 + TEST_GEN_FILES := \ 10 + napi_id_helper \ 11 + xdp_helper \ 12 + # end of TEST_GEN_FILES 10 13 11 14 TEST_PROGS := \ 15 + napi_id.py \ 12 16 netcons_basic.sh \ 13 17 netcons_fragmented_msg.sh \ 14 18 netcons_overflow.sh \
+56
tools/testing/selftests/drivers/net/ksft.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #if !defined(__NET_KSFT_H__) 3 + #define __NET_KSFT_H__ 4 + 5 + #include <stdio.h> 6 + #include <stdlib.h> 7 + #include <unistd.h> 8 + 9 + static inline void ksft_ready(void) 10 + { 11 + const char msg[7] = "ready\n"; 12 + char *env_str; 13 + int fd; 14 + 15 + env_str = getenv("KSFT_READY_FD"); 16 + if (env_str) { 17 + fd = atoi(env_str); 18 + if (!fd) { 19 + fprintf(stderr, "invalid KSFT_READY_FD = '%s'\n", 20 + env_str); 21 + return; 22 + } 23 + } else { 24 + fd = STDOUT_FILENO; 25 + } 26 + 27 + write(fd, msg, sizeof(msg)); 28 + if (fd != STDOUT_FILENO) 29 + close(fd); 30 + } 31 + 32 + static inline void ksft_wait(void) 33 + { 34 + char *env_str; 35 + char byte; 36 + int fd; 37 + 38 + env_str = getenv("KSFT_WAIT_FD"); 39 + if (env_str) { 40 + fd = atoi(env_str); 41 + if (!fd) { 42 + fprintf(stderr, "invalid KSFT_WAIT_FD = '%s'\n", 43 + env_str); 44 + return; 45 + } 46 + } else { 47 + /* Not running in KSFT env, wait for input from STDIN instead */ 48 + fd = STDIN_FILENO; 49 + } 50 + 51 + read(fd, &byte, sizeof(byte)); 52 + if (fd != STDIN_FILENO) 53 + close(fd); 54 + } 55 + 56 + #endif
+23
tools/testing/selftests/drivers/net/napi_id.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + from lib.py import ksft_run, ksft_exit 5 + from lib.py import ksft_eq, NetDrvEpEnv 6 + from lib.py import bkg, cmd, rand_port, NetNSEnter 7 + 8 + def test_napi_id(cfg) -> None: 9 + port = rand_port() 10 + listen_cmd = f"{cfg.test_dir}/napi_id_helper {cfg.addr_v['4']} {port}" 11 + 12 + with bkg(listen_cmd, ksft_wait=3) as server: 13 + cmd(f"echo a | socat - TCP:{cfg.addr_v['4']}:{port}", host=cfg.remote, shell=True) 14 + 15 + ksft_eq(0, server.ret) 16 + 17 + def main() -> None: 18 + with NetDrvEpEnv(__file__) as cfg: 19 + ksft_run([test_napi_id], args=(cfg,)) 20 + ksft_exit() 21 + 22 + if __name__ == "__main__": 23 + main()
+83
tools/testing/selftests/drivers/net/napi_id_helper.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <errno.h> 4 + #include <stdio.h> 5 + #include <stdlib.h> 6 + #include <string.h> 7 + #include <unistd.h> 8 + #include <arpa/inet.h> 9 + #include <sys/socket.h> 10 + 11 + #include "ksft.h" 12 + 13 + int main(int argc, char *argv[]) 14 + { 15 + struct sockaddr_in address; 16 + unsigned int napi_id; 17 + unsigned int port; 18 + socklen_t optlen; 19 + char buf[1024]; 20 + int opt = 1; 21 + int server; 22 + int client; 23 + int ret; 24 + 25 + server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 26 + if (server < 0) { 27 + perror("socket creation failed"); 28 + if (errno == EAFNOSUPPORT) 29 + return -1; 30 + return 1; 31 + } 32 + 33 + port = atoi(argv[2]); 34 + 35 + if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { 36 + perror("setsockopt"); 37 + return 1; 38 + } 39 + 40 + address.sin_family = AF_INET; 41 + inet_pton(AF_INET, argv[1], &address.sin_addr); 42 + address.sin_port = htons(port); 43 + 44 + if (bind(server, (struct sockaddr *)&address, sizeof(address)) < 0) { 45 + perror("bind failed"); 46 + return 1; 47 + } 48 + 49 + if (listen(server, 1) < 0) { 50 + perror("listen"); 51 + return 1; 52 + } 53 + 54 + ksft_ready(); 55 + 56 + client = accept(server, NULL, 0); 57 + if (client < 0) { 58 + perror("accept"); 59 + return 1; 60 + } 61 + 62 + optlen = sizeof(napi_id); 63 + ret = getsockopt(client, SOL_SOCKET, SO_INCOMING_NAPI_ID, &napi_id, 64 + &optlen); 65 + if (ret != 0) { 66 + perror("getsockopt"); 67 + return 1; 68 + } 69 + 70 + read(client, buf, 1024); 71 + 72 + ksft_wait(); 73 + 74 + if (napi_id == 0) { 75 + fprintf(stderr, "napi ID is 0\n"); 76 + return 1; 77 + } 78 + 79 + close(client); 80 + close(server); 81 + 82 + return 0; 83 + }
+2 -47
tools/testing/selftests/drivers/net/xdp_helper.c
··· 11 11 #include <net/if.h> 12 12 #include <inttypes.h> 13 13 14 + #include "ksft.h" 15 + 14 16 #define UMEM_SZ (1U << 16) 15 17 #define NUM_DESC (UMEM_SZ / 2048) 16 18 17 - /* Move this to a common header when reused! */ 18 - static void ksft_ready(void) 19 - { 20 - const char msg[7] = "ready\n"; 21 - char *env_str; 22 - int fd; 23 - 24 - env_str = getenv("KSFT_READY_FD"); 25 - if (env_str) { 26 - fd = atoi(env_str); 27 - if (!fd) { 28 - fprintf(stderr, "invalid KSFT_READY_FD = '%s'\n", 29 - env_str); 30 - return; 31 - } 32 - } else { 33 - fd = STDOUT_FILENO; 34 - } 35 - 36 - write(fd, msg, sizeof(msg)); 37 - if (fd != STDOUT_FILENO) 38 - close(fd); 39 - } 40 - 41 - static void ksft_wait(void) 42 - { 43 - char *env_str; 44 - char byte; 45 - int fd; 46 - 47 - env_str = getenv("KSFT_WAIT_FD"); 48 - if (env_str) { 49 - fd = atoi(env_str); 50 - if (!fd) { 51 - fprintf(stderr, "invalid KSFT_WAIT_FD = '%s'\n", 52 - env_str); 53 - return; 54 - } 55 - } else { 56 - /* Not running in KSFT env, wait for input from STDIN instead */ 57 - fd = STDIN_FILENO; 58 - } 59 - 60 - read(fd, &byte, sizeof(byte)); 61 - if (fd != STDIN_FILENO) 62 - close(fd); 63 - } 64 19 65 20 /* this is a simple helper program that creates an XDP socket and does the 66 21 * minimum necessary to get bind() to succeed.