History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next

Pull networking updates from Davic Miller: 1) Support busy polling generically, for all NAPI drivers. From Eric Dumazet. 2) Add byte/packet counter support to nft_ct, from Floriani Westphal. 3) Add RSS/XPS support to mvneta driver, from Gregory Clement. 4) Implement IPV6_HDRINCL socket option for raw sockets, from Hannes Frederic Sowa. 5) Add support for T6 adapter to cxgb4 driver, from Hariprasad Shenai. 6) Add support for VLAN device bridging to mlxsw switch driver, from Ido Schimmel. 7) Add driver for Netronome NFP4000/NFP6000, from Jakub Kicinski. 8) Provide hwmon interface to mlxsw switch driver, from Jiri Pirko. 9) Reorganize wireless drivers into per-vendor directories just like we do for ethernet drivers. From Kalle Valo. 10) Provide a way for administrators "destroy" connected sockets via the SOCK_DESTROY socket netlink diag operation. From Lorenzo Colitti. 11) Add support to add/remove multicast routes via netlink, from Nikolay Aleksandrov. 12) Make TCP keepalive settings per-namespace, from Nikolay Borisov. 13) Add forwarding and packet duplication facilities to nf_tables, from Pablo Neira Ayuso. 14) Dead route support in MPLS, from Roopa Prabhu. 15) TSO support for thunderx chips, from Sunil Goutham. 16) Add driver for IBM's System i/p VNIC protocol, from Thomas Falcon. 17) Rationalize, consolidate, and more completely document the checksum offloading facilities in the networking stack. From Tom Herbert. 18) Support aborting an ongoing scan in mac80211/cfg80211, from Vidyullatha Kanchanapally. 19) Use per-bucket spinlock for bpf hash facility, from Tom Leiming. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1375 commits) net: bnxt: always return values from _bnxt_get_max_rings net: bpf: reject invalid shifts phonet: properly unshare skbs in phonet_rcv() dwc_eth_qos: Fix dma address for multi-fragment skbs phy: remove an unneeded condition mdio: remove an unneed condition mdio_bus: NULL dereference on allocation error net: Fix typo in netdev_intersect_features net: freescale: mac-fec: Fix build error from phy_device API change net: freescale: ucc_geth: Fix build error from phy_device API change bonding: Prevent IPv6 link local address on enslaved devices IB/mlx5: Add flow steering support net/mlx5_core: Export flow steering API net/mlx5_core: Make ipv4/ipv6 location more clear net/mlx5_core: Enable flow steering support for the IB driver net/mlx5_core: Initialize namespaces only when supported by device net/mlx5_core: Set priority attributes net/mlx5_core: Connect flow tables net/mlx5_core: Introduce modify flow table command net/mlx5_core: Managing root flow table ...

Linus Torvalds committed 10 years ago

Commit aee3bfa2 parents c597b6b 415b6f11739 files · +70829 −25686Browse files

Showing the changes to tools/testing (3 of 1739 files). Show all

Unified · Split

3 files
  1. tools/testing/selftests/net/.gitignore +1 −0
  2. tools/testing/selftests/net/Makefile +1 −1
  3. tools/testing/selftests/net/reuseport_bpf.c +514 −0
tools/testing/selftests/net/.gitignore+1−0
@@ -1,3 +1,4 @@
1socket1socket
2psock_fanout2psock_fanout
3psock_tpacket3psock_tpacket
4reuseport_bpf
tools/testing/selftests/net/Makefile+1−1
@@ -4,7 +4,7 @@ CFLAGS = -Wall -O2 -g · 3 unmodified lines
4 4
5CFLAGS += -I../../../../usr/include/5CFLAGS += -I../../../../usr/include/
6 6
7NET_PROGS = socket psock_fanout psock_tpacket7NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf
8 8
9all: $(NET_PROGS)9all: $(NET_PROGS)
10%: %.c10%: %.c
tools/testing/selftests/net/reuseport_bpf.c+514−0
@@ -0,0 +1,514 @@
1/*
2 * Test functionality of BPF filters for SO_REUSEPORT. The tests below will use
3 * a BPF program (both classic and extended) to read the first word from an
4 * incoming packet (expected to be in network byte-order), calculate a modulus
5 * of that number, and then dispatch the packet to the Nth socket using the
6 * result. These tests are run for each supported address family and protocol.
7 * Additionally, a few edge cases in the implementation are tested.
8 */
9
10#include <errno.h>
11#include <error.h>
12#include <linux/bpf.h>
13#include <linux/filter.h>
14#include <linux/unistd.h>
15#include <netinet/in.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <sys/epoll.h>
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <unistd.h>
23
24#ifndef ARRAY_SIZE
25#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
26#endif
27
28struct test_params {
29 int recv_family;
30 int send_family;
31 int protocol;
32 size_t recv_socks;
33 uint16_t recv_port;
34 uint16_t send_port_min;
35};
36
37static size_t sockaddr_size(void)
38{
39 return sizeof(struct sockaddr_storage);
40}
41
42static struct sockaddr *new_any_sockaddr(int family, uint16_t port)
43{
44 struct sockaddr_storage *addr;
45 struct sockaddr_in *addr4;
46 struct sockaddr_in6 *addr6;
47
48 addr = malloc(sizeof(struct sockaddr_storage));
49 memset(addr, 0, sizeof(struct sockaddr_storage));
50
51 switch (family) {
52 case AF_INET:
53 addr4 = (struct sockaddr_in *)addr;
54 addr4->sin_family = AF_INET;
55 addr4->sin_addr.s_addr = htonl(INADDR_ANY);
56 addr4->sin_port = htons(port);
57 break;
58 case AF_INET6:
59 addr6 = (struct sockaddr_in6 *)addr;
60 addr6->sin6_family = AF_INET6;
61 addr6->sin6_addr = in6addr_any;
62 addr6->sin6_port = htons(port);
63 break;
64 default:
65 error(1, 0, "Unsupported family %d", family);
66 }
67 return (struct sockaddr *)addr;
68}
69
70static struct sockaddr *new_loopback_sockaddr(int family, uint16_t port)
71{
72 struct sockaddr *addr = new_any_sockaddr(family, port);
73 struct sockaddr_in *addr4;
74 struct sockaddr_in6 *addr6;
75
76 switch (family) {
77 case AF_INET:
78 addr4 = (struct sockaddr_in *)addr;
79 addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
80 break;
81 case AF_INET6:
82 addr6 = (struct sockaddr_in6 *)addr;
83 addr6->sin6_addr = in6addr_loopback;
84 break;
85 default:
86 error(1, 0, "Unsupported family %d", family);
87 }
88 return addr;
89}
90
91static void attach_ebpf(int fd, uint16_t mod)
92{
93 static char bpf_log_buf[65536];
94 static const char bpf_license[] = "GPL";
95
96 int bpf_fd;
97 const struct bpf_insn prog[] = {
98 /* BPF_MOV64_REG(BPF_REG_6, BPF_REG_1) */
99 { BPF_ALU64 | BPF_MOV | BPF_X, BPF_REG_6, BPF_REG_1, 0, 0 },
100 /* BPF_LD_ABS(BPF_W, 0) R0 = (uint32_t)skb[0] */
101 { BPF_LD | BPF_ABS | BPF_W, 0, 0, 0, 0 },
102 /* BPF_ALU64_IMM(BPF_MOD, BPF_REG_0, mod) */
103 { BPF_ALU64 | BPF_MOD | BPF_K, BPF_REG_0, 0, 0, mod },
104 /* BPF_EXIT_INSN() */
105 { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
106 };
107 union bpf_attr attr;
108
109 memset(&attr, 0, sizeof(attr));
110 attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
111 attr.insn_cnt = ARRAY_SIZE(prog);
112 attr.insns = (uint64_t)prog;
113 attr.license = (uint64_t)bpf_license;
114 attr.log_buf = (uint64_t)bpf_log_buf;
115 attr.log_size = sizeof(bpf_log_buf);
116 attr.log_level = 1;
117 attr.kern_version = 0;
118
119 bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
120 if (bpf_fd < 0)
121 error(1, errno, "ebpf error. log:\n%s\n", bpf_log_buf);
122
123 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
124 sizeof(bpf_fd)))
125 error(1, errno, "failed to set SO_ATTACH_REUSEPORT_EBPF");
126
127 close(bpf_fd);
128}
129
130static void attach_cbpf(int fd, uint16_t mod)
131{
132 struct sock_filter code[] = {
133 /* A = (uint32_t)skb[0] */
134 { BPF_LD | BPF_W | BPF_ABS, 0, 0, 0 },
135 /* A = A % mod */
136 { BPF_ALU | BPF_MOD, 0, 0, mod },
137 /* return A */
138 { BPF_RET | BPF_A, 0, 0, 0 },
139 };
140 struct sock_fprog p = {
141 .len = ARRAY_SIZE(code),
142 .filter = code,
143 };
144
145 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &p, sizeof(p)))
146 error(1, errno, "failed to set SO_ATTACH_REUSEPORT_CBPF");
147}
148
149static void build_recv_group(const struct test_params p, int fd[], uint16_t mod,
150 void (*attach_bpf)(int, uint16_t))
151{
152 struct sockaddr * const addr =
153 new_any_sockaddr(p.recv_family, p.recv_port);
154 int i, opt;
155
156 for (i = 0; i < p.recv_socks; ++i) {
157 fd[i] = socket(p.recv_family, p.protocol, 0);
158 if (fd[i] < 0)
159 error(1, errno, "failed to create recv %d", i);
160
161 opt = 1;
162 if (setsockopt(fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
163 sizeof(opt)))
164 error(1, errno, "failed to set SO_REUSEPORT on %d", i);
165
166 if (i == 0)
167 attach_bpf(fd[i], mod);
168
169 if (bind(fd[i], addr, sockaddr_size()))
170 error(1, errno, "failed to bind recv socket %d", i);
171
172 if (p.protocol == SOCK_STREAM)
173 if (listen(fd[i], p.recv_socks * 10))
174 error(1, errno, "failed to listen on socket");
175 }
176 free(addr);
177}
178
179static void send_from(struct test_params p, uint16_t sport, char *buf,
180 size_t len)
181{
182 struct sockaddr * const saddr = new_any_sockaddr(p.send_family, sport);
183 struct sockaddr * const daddr =
184 new_loopback_sockaddr(p.send_family, p.recv_port);
185 const int fd = socket(p.send_family, p.protocol, 0);
186
187 if (fd < 0)
188 error(1, errno, "failed to create send socket");
189
190 if (bind(fd, saddr, sockaddr_size()))
191 error(1, errno, "failed to bind send socket");
192 if (connect(fd, daddr, sockaddr_size()))
193 error(1, errno, "failed to connect");
194
195 if (send(fd, buf, len, 0) < 0)
196 error(1, errno, "failed to send message");
197
198 close(fd);
199 free(saddr);
200 free(daddr);
201}
202
203static void test_recv_order(const struct test_params p, int fd[], int mod)
204{
205 char recv_buf[8], send_buf[8];
206 struct msghdr msg;
207 struct iovec recv_io = { recv_buf, 8 };
208 struct epoll_event ev;
209 int epfd, conn, i, sport, expected;
210 uint32_t data, ndata;
211
212 epfd = epoll_create(1);
213 if (epfd < 0)
214 error(1, errno, "failed to create epoll");
215 for (i = 0; i < p.recv_socks; ++i) {
216 ev.events = EPOLLIN;
217 ev.data.fd = fd[i];
218 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd[i], &ev))
219 error(1, errno, "failed to register sock %d epoll", i);
220 }
221
222 memset(&msg, 0, sizeof(msg));
223 msg.msg_iov = &recv_io;
224 msg.msg_iovlen = 1;
225
226 for (data = 0; data < p.recv_socks * 2; ++data) {
227 sport = p.send_port_min + data;
228 ndata = htonl(data);
229 memcpy(send_buf, &ndata, sizeof(ndata));
230 send_from(p, sport, send_buf, sizeof(ndata));
231
232 i = epoll_wait(epfd, &ev, 1, -1);
233 if (i < 0)
234 error(1, errno, "epoll wait failed");
235
236 if (p.protocol == SOCK_STREAM) {
237 conn = accept(ev.data.fd, NULL, NULL);
238 if (conn < 0)
239 error(1, errno, "error accepting");
240 i = recvmsg(conn, &msg, 0);
241 close(conn);
242 } else {
243 i = recvmsg(ev.data.fd, &msg, 0);
244 }
245 if (i < 0)
246 error(1, errno, "recvmsg error");
247 if (i != sizeof(ndata))
248 error(1, 0, "expected size %zd got %d",
249 sizeof(ndata), i);
250
251 for (i = 0; i < p.recv_socks; ++i)
252 if (ev.data.fd == fd[i])
253 break;
254 memcpy(&ndata, recv_buf, sizeof(ndata));
255 fprintf(stderr, "Socket %d: %d\n", i, ntohl(ndata));
256
257 expected = (sport % mod);
258 if (i != expected)
259 error(1, 0, "expected socket %d", expected);
260 }
261}
262
263static void test_reuseport_ebpf(const struct test_params p)
264{
265 int i, fd[p.recv_socks];
266
267 fprintf(stderr, "Testing EBPF mod %zd...\n", p.recv_socks);
268 build_recv_group(p, fd, p.recv_socks, attach_ebpf);
269 test_recv_order(p, fd, p.recv_socks);
270
271 fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
272 attach_ebpf(fd[0], p.recv_socks / 2);
273 test_recv_order(p, fd, p.recv_socks / 2);
274
275 for (i = 0; i < p.recv_socks; ++i)
276 close(fd[i]);
277}
278
279static void test_reuseport_cbpf(const struct test_params p)
280{
281 int i, fd[p.recv_socks];
282
283 fprintf(stderr, "Testing CBPF mod %zd...\n", p.recv_socks);
284 build_recv_group(p, fd, p.recv_socks, attach_cbpf);
285 test_recv_order(p, fd, p.recv_socks);
286
287 fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
288 attach_cbpf(fd[0], p.recv_socks / 2);
289 test_recv_order(p, fd, p.recv_socks / 2);
290
291 for (i = 0; i < p.recv_socks; ++i)
292 close(fd[i]);
293}
294
295static void test_extra_filter(const struct test_params p)
296{
297 struct sockaddr * const addr =
298 new_any_sockaddr(p.recv_family, p.recv_port);
299 int fd1, fd2, opt;
300
301 fprintf(stderr, "Testing too many filters...\n");
302 fd1 = socket(p.recv_family, p.protocol, 0);
303 if (fd1 < 0)
304 error(1, errno, "failed to create socket 1");
305 fd2 = socket(p.recv_family, p.protocol, 0);
306 if (fd2 < 0)
307 error(1, errno, "failed to create socket 2");
308
309 opt = 1;
310 if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
311 error(1, errno, "failed to set SO_REUSEPORT on socket 1");
312 if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
313 error(1, errno, "failed to set SO_REUSEPORT on socket 2");
314
315 attach_ebpf(fd1, 10);
316 attach_ebpf(fd2, 10);
317
318 if (bind(fd1, addr, sockaddr_size()))
319 error(1, errno, "failed to bind recv socket 1");
320
321 if (!bind(fd2, addr, sockaddr_size()) && errno != EADDRINUSE)
322 error(1, errno, "bind socket 2 should fail with EADDRINUSE");
323
324 free(addr);
325}
326
327static void test_filter_no_reuseport(const struct test_params p)
328{
329 struct sockaddr * const addr =
330 new_any_sockaddr(p.recv_family, p.recv_port);
331 const char bpf_license[] = "GPL";
332 struct bpf_insn ecode[] = {
333 { BPF_ALU64 | BPF_MOV | BPF_K, BPF_REG_0, 0, 0, 10 },
334 { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
335 };
336 struct sock_filter ccode[] = {{ BPF_RET | BPF_A, 0, 0, 0 }};
337 union bpf_attr eprog;
338 struct sock_fprog cprog;
339 int fd, bpf_fd;
340
341 fprintf(stderr, "Testing filters on non-SO_REUSEPORT socket...\n");
342
343 memset(&eprog, 0, sizeof(eprog));
344 eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
345 eprog.insn_cnt = ARRAY_SIZE(ecode);
346 eprog.insns = (uint64_t)ecode;
347 eprog.license = (uint64_t)bpf_license;
348 eprog.kern_version = 0;
349
350 memset(&cprog, 0, sizeof(cprog));
351 cprog.len = ARRAY_SIZE(ccode);
352 cprog.filter = ccode;
353
354
355 bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &eprog, sizeof(eprog));
356 if (bpf_fd < 0)
357 error(1, errno, "ebpf error");
358 fd = socket(p.recv_family, p.protocol, 0);
359 if (fd < 0)
360 error(1, errno, "failed to create socket 1");
361
362 if (bind(fd, addr, sockaddr_size()))
363 error(1, errno, "failed to bind recv socket 1");
364
365 errno = 0;
366 if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
367 sizeof(bpf_fd)) || errno != EINVAL)
368 error(1, errno, "setsockopt should have returned EINVAL");
369
370 errno = 0;
371 if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &cprog,
372 sizeof(cprog)) || errno != EINVAL)
373 error(1, errno, "setsockopt should have returned EINVAL");
374
375 free(addr);
376}
377
378static void test_filter_without_bind(void)
379{
380 int fd1, fd2;
381
382 fprintf(stderr, "Testing filter add without bind...\n");
383 fd1 = socket(AF_INET, SOCK_DGRAM, 0);
384 if (fd1 < 0)
385 error(1, errno, "failed to create socket 1");
386 fd2 = socket(AF_INET, SOCK_DGRAM, 0);
387 if (fd2 < 0)
388 error(1, errno, "failed to create socket 2");
389
390 attach_ebpf(fd1, 10);
391 attach_cbpf(fd2, 10);
392
393 close(fd1);
394 close(fd2);
395}
396
397
398int main(void)
399{
400 fprintf(stderr, "---- IPv4 UDP ----\n");
401 /* NOTE: UDP socket lookups traverse a different code path when there
402 * are > 10 sockets in a group. Run the bpf test through both paths.
403 */
404 test_reuseport_ebpf((struct test_params) {
405 .recv_family = AF_INET,
406 .send_family = AF_INET,
407 .protocol = SOCK_DGRAM,
408 .recv_socks = 10,
409 .recv_port = 8000,
410 .send_port_min = 9000});
411 test_reuseport_ebpf((struct test_params) {
412 .recv_family = AF_INET,
413 .send_family = AF_INET,
414 .protocol = SOCK_DGRAM,
415 .recv_socks = 20,
416 .recv_port = 8000,
417 .send_port_min = 9000});
418 test_reuseport_cbpf((struct test_params) {
419 .recv_family = AF_INET,
420 .send_family = AF_INET,
421 .protocol = SOCK_DGRAM,
422 .recv_socks = 10,
423 .recv_port = 8001,
424 .send_port_min = 9020});
425 test_reuseport_cbpf((struct test_params) {
426 .recv_family = AF_INET,
427 .send_family = AF_INET,
428 .protocol = SOCK_DGRAM,
429 .recv_socks = 20,
430 .recv_port = 8001,
431 .send_port_min = 9020});
432 test_extra_filter((struct test_params) {
433 .recv_family = AF_INET,
434 .protocol = SOCK_DGRAM,
435 .recv_port = 8002});
436 test_filter_no_reuseport((struct test_params) {
437 .recv_family = AF_INET,
438 .protocol = SOCK_DGRAM,
439 .recv_port = 8008});
440
441 fprintf(stderr, "---- IPv6 UDP ----\n");
442 test_reuseport_ebpf((struct test_params) {
443 .recv_family = AF_INET6,
444 .send_family = AF_INET6,
445 .protocol = SOCK_DGRAM,
446 .recv_socks = 10,
447 .recv_port = 8003,
448 .send_port_min = 9040});
449 test_reuseport_ebpf((struct test_params) {
450 .recv_family = AF_INET6,
451 .send_family = AF_INET6,
452 .protocol = SOCK_DGRAM,
453 .recv_socks = 20,
454 .recv_port = 8003,
455 .send_port_min = 9040});
456 test_reuseport_cbpf((struct test_params) {
457 .recv_family = AF_INET6,
458 .send_family = AF_INET6,
459 .protocol = SOCK_DGRAM,
460 .recv_socks = 10,
461 .recv_port = 8004,
462 .send_port_min = 9060});
463 test_reuseport_cbpf((struct test_params) {
464 .recv_family = AF_INET6,
465 .send_family = AF_INET6,
466 .protocol = SOCK_DGRAM,
467 .recv_socks = 20,
468 .recv_port = 8004,
469 .send_port_min = 9060});
470 test_extra_filter((struct test_params) {
471 .recv_family = AF_INET6,
472 .protocol = SOCK_DGRAM,
473 .recv_port = 8005});
474 test_filter_no_reuseport((struct test_params) {
475 .recv_family = AF_INET6,
476 .protocol = SOCK_DGRAM,
477 .recv_port = 8009});
478
479 fprintf(stderr, "---- IPv6 UDP w/ mapped IPv4 ----\n");
480 test_reuseport_ebpf((struct test_params) {
481 .recv_family = AF_INET6,
482 .send_family = AF_INET,
483 .protocol = SOCK_DGRAM,
484 .recv_socks = 20,
485 .recv_port = 8006,
486 .send_port_min = 9080});
487 test_reuseport_ebpf((struct test_params) {
488 .recv_family = AF_INET6,
489 .send_family = AF_INET,
490 .protocol = SOCK_DGRAM,
491 .recv_socks = 10,
492 .recv_port = 8006,
493 .send_port_min = 9080});
494 test_reuseport_cbpf((struct test_params) {
495 .recv_family = AF_INET6,
496 .send_family = AF_INET,
497 .protocol = SOCK_DGRAM,
498 .recv_socks = 10,
499 .recv_port = 8007,
500 .send_port_min = 9100});
501 test_reuseport_cbpf((struct test_params) {
502 .recv_family = AF_INET6,
503 .send_family = AF_INET,
504 .protocol = SOCK_DGRAM,
505 .recv_socks = 20,
506 .recv_port = 8007,
507 .send_port_min = 9100});
508
509
510 test_filter_without_bind();
511
512 fprintf(stderr, "SUCCESS\n");
513 return 0;
514}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t