1 // SPDX-License-Identifier: GPL-2.0
3 * Test functionality of BPF filters with SO_REUSEPORT. Same test as
4 * in reuseport_bpf_cpu, only as one socket per NUMA node.
12 #include <linux/filter.h>
13 #include <linux/bpf.h>
15 #include <linux/unistd.h>
20 #include <sys/epoll.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
26 #include "../kselftest.h"
28 static const int PORT
= 8888;
30 static void build_rcv_group(int *rcv_fd
, size_t len
, int family
, int proto
)
32 struct sockaddr_storage addr
;
33 struct sockaddr_in
*addr4
;
34 struct sockaddr_in6
*addr6
;
40 addr4
= (struct sockaddr_in
*)&addr
;
41 addr4
->sin_family
= AF_INET
;
42 addr4
->sin_addr
.s_addr
= htonl(INADDR_ANY
);
43 addr4
->sin_port
= htons(PORT
);
46 addr6
= (struct sockaddr_in6
*)&addr
;
47 addr6
->sin6_family
= AF_INET6
;
48 addr6
->sin6_addr
= in6addr_any
;
49 addr6
->sin6_port
= htons(PORT
);
52 error(1, 0, "Unsupported family %d", family
);
55 for (i
= 0; i
< len
; ++i
) {
56 rcv_fd
[i
] = socket(family
, proto
, 0);
58 error(1, errno
, "failed to create receive socket");
61 if (setsockopt(rcv_fd
[i
], SOL_SOCKET
, SO_REUSEPORT
, &opt
,
63 error(1, errno
, "failed to set SO_REUSEPORT");
65 if (bind(rcv_fd
[i
], (struct sockaddr
*)&addr
, sizeof(addr
)))
66 error(1, errno
, "failed to bind receive socket");
68 if (proto
== SOCK_STREAM
&& listen(rcv_fd
[i
], len
* 10))
69 error(1, errno
, "failed to listen on receive port");
73 static void attach_bpf(int fd
)
75 static char bpf_log_buf
[65536];
76 static const char bpf_license
[] = "";
79 const struct bpf_insn prog
[] = {
80 /* R0 = bpf_get_numa_node_id() */
81 { BPF_JMP
| BPF_CALL
, 0, 0, 0, BPF_FUNC_get_numa_node_id
},
83 { BPF_JMP
| BPF_EXIT
, 0, 0, 0, 0 }
87 memset(&attr
, 0, sizeof(attr
));
88 attr
.prog_type
= BPF_PROG_TYPE_SOCKET_FILTER
;
89 attr
.insn_cnt
= ARRAY_SIZE(prog
);
90 attr
.insns
= (unsigned long) &prog
;
91 attr
.license
= (unsigned long) &bpf_license
;
92 attr
.log_buf
= (unsigned long) &bpf_log_buf
;
93 attr
.log_size
= sizeof(bpf_log_buf
);
96 bpf_fd
= syscall(__NR_bpf
, BPF_PROG_LOAD
, &attr
, sizeof(attr
));
98 error(1, errno
, "ebpf error. log:\n%s\n", bpf_log_buf
);
100 if (setsockopt(fd
, SOL_SOCKET
, SO_ATTACH_REUSEPORT_EBPF
, &bpf_fd
,
102 error(1, errno
, "failed to set SO_ATTACH_REUSEPORT_EBPF");
107 static void send_from_node(int node_id
, int family
, int proto
)
109 struct sockaddr_storage saddr
, daddr
;
110 struct sockaddr_in
*saddr4
, *daddr4
;
111 struct sockaddr_in6
*saddr6
, *daddr6
;
116 saddr4
= (struct sockaddr_in
*)&saddr
;
117 saddr4
->sin_family
= AF_INET
;
118 saddr4
->sin_addr
.s_addr
= htonl(INADDR_ANY
);
119 saddr4
->sin_port
= 0;
121 daddr4
= (struct sockaddr_in
*)&daddr
;
122 daddr4
->sin_family
= AF_INET
;
123 daddr4
->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
124 daddr4
->sin_port
= htons(PORT
);
127 saddr6
= (struct sockaddr_in6
*)&saddr
;
128 saddr6
->sin6_family
= AF_INET6
;
129 saddr6
->sin6_addr
= in6addr_any
;
130 saddr6
->sin6_port
= 0;
132 daddr6
= (struct sockaddr_in6
*)&daddr
;
133 daddr6
->sin6_family
= AF_INET6
;
134 daddr6
->sin6_addr
= in6addr_loopback
;
135 daddr6
->sin6_port
= htons(PORT
);
138 error(1, 0, "Unsupported family %d", family
);
141 if (numa_run_on_node(node_id
) < 0)
142 error(1, errno
, "failed to pin to node");
144 fd
= socket(family
, proto
, 0);
146 error(1, errno
, "failed to create send socket");
148 if (bind(fd
, (struct sockaddr
*)&saddr
, sizeof(saddr
)))
149 error(1, errno
, "failed to bind send socket");
151 if (connect(fd
, (struct sockaddr
*)&daddr
, sizeof(daddr
)))
152 error(1, errno
, "failed to connect send socket");
154 if (send(fd
, "a", 1, 0) < 0)
155 error(1, errno
, "failed to send message");
161 void receive_on_node(int *rcv_fd
, int len
, int epfd
, int node_id
, int proto
)
163 struct epoll_event ev
;
167 i
= epoll_wait(epfd
, &ev
, 1, -1);
169 error(1, errno
, "epoll_wait failed");
171 if (proto
== SOCK_STREAM
) {
172 fd
= accept(ev
.data
.fd
, NULL
, NULL
);
174 error(1, errno
, "failed to accept");
175 i
= recv(fd
, buf
, sizeof(buf
), 0);
178 i
= recv(ev
.data
.fd
, buf
, sizeof(buf
), 0);
182 error(1, errno
, "failed to recv");
184 for (i
= 0; i
< len
; ++i
)
185 if (ev
.data
.fd
== rcv_fd
[i
])
188 error(1, 0, "failed to find socket");
189 fprintf(stderr
, "send node %d, receive socket %d\n", node_id
, i
);
191 error(1, 0, "node id/receive socket mismatch");
194 static void test(int *rcv_fd
, int len
, int family
, int proto
)
196 struct epoll_event ev
;
199 build_rcv_group(rcv_fd
, len
, family
, proto
);
200 attach_bpf(rcv_fd
[0]);
202 epfd
= epoll_create(1);
204 error(1, errno
, "failed to create epoll");
205 for (node
= 0; node
< len
; ++node
) {
207 ev
.data
.fd
= rcv_fd
[node
];
208 if (epoll_ctl(epfd
, EPOLL_CTL_ADD
, rcv_fd
[node
], &ev
))
209 error(1, errno
, "failed to register sock epoll");
212 /* Forward iterate */
213 for (node
= 0; node
< len
; ++node
) {
214 if (!numa_bitmask_isbitset(numa_nodes_ptr
, node
))
216 send_from_node(node
, family
, proto
);
217 receive_on_node(rcv_fd
, len
, epfd
, node
, proto
);
220 /* Reverse iterate */
221 for (node
= len
- 1; node
>= 0; --node
) {
222 if (!numa_bitmask_isbitset(numa_nodes_ptr
, node
))
224 send_from_node(node
, family
, proto
);
225 receive_on_node(rcv_fd
, len
, epfd
, node
, proto
);
229 for (node
= 0; node
< len
; ++node
)
237 if (numa_available() < 0)
238 ksft_exit_skip("no numa api support\n");
240 nodes
= numa_max_node() + 1;
242 rcv_fd
= calloc(nodes
, sizeof(int));
244 error(1, 0, "failed to allocate array");
246 fprintf(stderr
, "---- IPv4 UDP ----\n");
247 test(rcv_fd
, nodes
, AF_INET
, SOCK_DGRAM
);
249 fprintf(stderr
, "---- IPv6 UDP ----\n");
250 test(rcv_fd
, nodes
, AF_INET6
, SOCK_DGRAM
);
252 fprintf(stderr
, "---- IPv4 TCP ----\n");
253 test(rcv_fd
, nodes
, AF_INET
, SOCK_STREAM
);
255 fprintf(stderr
, "---- IPv6 TCP ----\n");
256 test(rcv_fd
, nodes
, AF_INET6
, SOCK_STREAM
);
260 fprintf(stderr
, "SUCCESS\n");