Skip to content

Commit 4acf6d4

Browse files
committed
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>
2 parents f74d14a + 2593a0a commit 4acf6d4

File tree

7 files changed

+172
-48
lines changed

7 files changed

+172
-48
lines changed

drivers/net/netdevsim/netdev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <net/pkt_cls.h>
3030
#include <net/rtnetlink.h>
3131
#include <net/udp_tunnel.h>
32+
#include <net/busy_poll.h>
3233

3334
#include "netdevsim.h"
3435

@@ -357,6 +358,7 @@ static int nsim_rcv(struct nsim_rq *rq, int budget)
357358
break;
358359

359360
skb = skb_dequeue(&rq->skb_queue);
361+
skb_mark_napi_id(skb, &rq->napi);
360362
netif_receive_skb(skb);
361363
}
362364

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
# SPDX-License-Identifier: GPL-2.0-only
2+
napi_id_helper
23
xdp_helper

tools/testing/selftests/drivers/net/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ TEST_INCLUDES := $(wildcard lib/py/*.py) \
66
../../net/net_helper.sh \
77
../../net/lib.sh \
88

9-
TEST_GEN_FILES := xdp_helper
9+
TEST_GEN_FILES := \
10+
napi_id_helper \
11+
xdp_helper \
12+
# end of TEST_GEN_FILES
1013

1114
TEST_PROGS := \
15+
napi_id.py \
1216
netcons_basic.sh \
1317
netcons_fragmented_msg.sh \
1418
netcons_overflow.sh \
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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()
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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+
}

tools/testing/selftests/drivers/net/xdp_helper.c

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,56 +11,11 @@
1111
#include <net/if.h>
1212
#include <inttypes.h>
1313

14+
#include "ksft.h"
15+
1416
#define UMEM_SZ (1U << 16)
1517
#define NUM_DESC (UMEM_SZ / 2048)
1618

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-
}
6419

6520
/* this is a simple helper program that creates an XDP socket and does the
6621
* minimum necessary to get bind() to succeed.

0 commit comments

Comments
 (0)