aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-03-19 13:05:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-19 13:05:34 -0400
commit1200b6809dfd9d73bc4c7db76d288c35fa4b2ebe (patch)
tree552e03de245cdbd0780ca1215914edc4a26540f7 /tools/testing/selftests/net
parent6b5f04b6cf8ebab9a65d9c0026c650bb2538fd0f (diff)
parentfe30937b65354c7fec244caebbdaae68e28ca797 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: "Highlights: 1) Support more Realtek wireless chips, from Jes Sorenson. 2) New BPF types for per-cpu hash and arrap maps, from Alexei Starovoitov. 3) Make several TCP sysctls per-namespace, from Nikolay Borisov. 4) Allow the use of SO_REUSEPORT in order to do per-thread processing of incoming TCP/UDP connections. The muxing can be done using a BPF program which hashes the incoming packet. From Craig Gallek. 5) Add a multiplexer for TCP streams, to provide a messaged based interface. BPF programs can be used to determine the message boundaries. From Tom Herbert. 6) Add 802.1AE MACSEC support, from Sabrina Dubroca. 7) Avoid factorial complexity when taking down an inetdev interface with lots of configured addresses. We were doing things like traversing the entire address less for each address removed, and flushing the entire netfilter conntrack table for every address as well. 8) Add and use SKB bulk free infrastructure, from Jesper Brouer. 9) Allow offloading u32 classifiers to hardware, and implement for ixgbe, from John Fastabend. 10) Allow configuring IRQ coalescing parameters on a per-queue basis, from Kan Liang. 11) Extend ethtool so that larger link mode masks can be supported. From David Decotigny. 12) Introduce devlink, which can be used to configure port link types (ethernet vs Infiniband, etc.), port splitting, and switch device level attributes as a whole. From Jiri Pirko. 13) Hardware offload support for flower classifiers, from Amir Vadai. 14) Add "Local Checksum Offload". Basically, for a tunneled packet the checksum of the outer header is 'constant' (because with the checksum field filled into the inner protocol header, the payload of the outer frame checksums to 'zero'), and we can take advantage of that in various ways. From Edward Cree" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1548 commits) bonding: fix bond_get_stats() net: bcmgenet: fix dma api length mismatch net/mlx4_core: Fix backward compatibility on VFs phy: mdio-thunder: Fix some Kconfig typos lan78xx: add ndo_get_stats64 lan78xx: handle statistics counter rollover RDS: TCP: Remove unused constant RDS: TCP: Add sysctl tunables for sndbuf/rcvbuf on rds-tcp socket net: smc911x: convert pxa dma to dmaengine team: remove duplicate set of flag IFF_MULTICAST bonding: remove duplicate set of flag IFF_MULTICAST net: fix a comment typo ethernet: micrel: fix some error codes ip_tunnels, bpf: define IP_TUNNEL_OPTS_MAX and use it bpf, dst: add and use dst_tclassid helper bpf: make skb->tc_classid also readable net: mvneta: bm: clarify dependencies cls_bpf: reset class and reuse major in da ldmvsw: Checkpatch sunvnet.c and sunvnet_common.c ldmvsw: Add ldmvsw.c driver code ...
Diffstat (limited to 'tools/testing/selftests/net')
-rw-r--r--tools/testing/selftests/net/.gitignore1
-rw-r--r--tools/testing/selftests/net/Makefile2
-rw-r--r--tools/testing/selftests/net/reuseport_bpf.c117
-rw-r--r--tools/testing/selftests/net/reuseport_bpf_cpu.c258
4 files changed, 370 insertions, 8 deletions
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index 6fb23366b258..69bb3fc38fb2 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -2,3 +2,4 @@ socket
2psock_fanout 2psock_fanout
3psock_tpacket 3psock_tpacket
4reuseport_bpf 4reuseport_bpf
5reuseport_bpf_cpu
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 41449b5ad0a9..c658792d47b4 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -4,7 +4,7 @@ CFLAGS = -Wall -O2 -g
4 4
5CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
6 6
7NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf 7NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf reuseport_bpf_cpu
8 8
9all: $(NET_PROGS) 9all: $(NET_PROGS)
10%: %.c 10%: %.c
diff --git a/tools/testing/selftests/net/reuseport_bpf.c b/tools/testing/selftests/net/reuseport_bpf.c
index bec1b5dd2530..96ba386b1b7b 100644
--- a/tools/testing/selftests/net/reuseport_bpf.c
+++ b/tools/testing/selftests/net/reuseport_bpf.c
@@ -9,10 +9,12 @@
9 9
10#include <errno.h> 10#include <errno.h>
11#include <error.h> 11#include <error.h>
12#include <fcntl.h>
12#include <linux/bpf.h> 13#include <linux/bpf.h>
13#include <linux/filter.h> 14#include <linux/filter.h>
14#include <linux/unistd.h> 15#include <linux/unistd.h>
15#include <netinet/in.h> 16#include <netinet/in.h>
17#include <netinet/tcp.h>
16#include <stdio.h> 18#include <stdio.h>
17#include <stdlib.h> 19#include <stdlib.h>
18#include <string.h> 20#include <string.h>
@@ -169,9 +171,15 @@ static void build_recv_group(const struct test_params p, int fd[], uint16_t mod,
169 if (bind(fd[i], addr, sockaddr_size())) 171 if (bind(fd[i], addr, sockaddr_size()))
170 error(1, errno, "failed to bind recv socket %d", i); 172 error(1, errno, "failed to bind recv socket %d", i);
171 173
172 if (p.protocol == SOCK_STREAM) 174 if (p.protocol == SOCK_STREAM) {
175 opt = 4;
176 if (setsockopt(fd[i], SOL_TCP, TCP_FASTOPEN, &opt,
177 sizeof(opt)))
178 error(1, errno,
179 "failed to set TCP_FASTOPEN on %d", i);
173 if (listen(fd[i], p.recv_socks * 10)) 180 if (listen(fd[i], p.recv_socks * 10))
174 error(1, errno, "failed to listen on socket"); 181 error(1, errno, "failed to listen on socket");
182 }
175 } 183 }
176 free(addr); 184 free(addr);
177} 185}
@@ -189,10 +197,8 @@ static void send_from(struct test_params p, uint16_t sport, char *buf,
189 197
190 if (bind(fd, saddr, sockaddr_size())) 198 if (bind(fd, saddr, sockaddr_size()))
191 error(1, errno, "failed to bind send socket"); 199 error(1, errno, "failed to bind send socket");
192 if (connect(fd, daddr, sockaddr_size()))
193 error(1, errno, "failed to connect");
194 200
195 if (send(fd, buf, len, 0) < 0) 201 if (sendto(fd, buf, len, MSG_FASTOPEN, daddr, sockaddr_size()) < 0)
196 error(1, errno, "failed to send message"); 202 error(1, errno, "failed to send message");
197 203
198 close(fd); 204 close(fd);
@@ -260,7 +266,7 @@ static void test_recv_order(const struct test_params p, int fd[], int mod)
260 } 266 }
261} 267}
262 268
263static void test_reuseport_ebpf(const struct test_params p) 269static void test_reuseport_ebpf(struct test_params p)
264{ 270{
265 int i, fd[p.recv_socks]; 271 int i, fd[p.recv_socks];
266 272
@@ -268,6 +274,7 @@ static void test_reuseport_ebpf(const struct test_params p)
268 build_recv_group(p, fd, p.recv_socks, attach_ebpf); 274 build_recv_group(p, fd, p.recv_socks, attach_ebpf);
269 test_recv_order(p, fd, p.recv_socks); 275 test_recv_order(p, fd, p.recv_socks);
270 276
277 p.send_port_min += p.recv_socks * 2;
271 fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2); 278 fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
272 attach_ebpf(fd[0], p.recv_socks / 2); 279 attach_ebpf(fd[0], p.recv_socks / 2);
273 test_recv_order(p, fd, p.recv_socks / 2); 280 test_recv_order(p, fd, p.recv_socks / 2);
@@ -276,7 +283,7 @@ static void test_reuseport_ebpf(const struct test_params p)
276 close(fd[i]); 283 close(fd[i]);
277} 284}
278 285
279static void test_reuseport_cbpf(const struct test_params p) 286static void test_reuseport_cbpf(struct test_params p)
280{ 287{
281 int i, fd[p.recv_socks]; 288 int i, fd[p.recv_socks];
282 289
@@ -284,6 +291,7 @@ static void test_reuseport_cbpf(const struct test_params p)
284 build_recv_group(p, fd, p.recv_socks, attach_cbpf); 291 build_recv_group(p, fd, p.recv_socks, attach_cbpf);
285 test_recv_order(p, fd, p.recv_socks); 292 test_recv_order(p, fd, p.recv_socks);
286 293
294 p.send_port_min += p.recv_socks * 2;
287 fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2); 295 fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
288 attach_cbpf(fd[0], p.recv_socks / 2); 296 attach_cbpf(fd[0], p.recv_socks / 2);
289 test_recv_order(p, fd, p.recv_socks / 2); 297 test_recv_order(p, fd, p.recv_socks / 2);
@@ -377,7 +385,7 @@ static void test_filter_no_reuseport(const struct test_params p)
377 385
378static void test_filter_without_bind(void) 386static void test_filter_without_bind(void)
379{ 387{
380 int fd1, fd2; 388 int fd1, fd2, opt = 1;
381 389
382 fprintf(stderr, "Testing filter add without bind...\n"); 390 fprintf(stderr, "Testing filter add without bind...\n");
383 fd1 = socket(AF_INET, SOCK_DGRAM, 0); 391 fd1 = socket(AF_INET, SOCK_DGRAM, 0);
@@ -386,6 +394,10 @@ static void test_filter_without_bind(void)
386 fd2 = socket(AF_INET, SOCK_DGRAM, 0); 394 fd2 = socket(AF_INET, SOCK_DGRAM, 0);
387 if (fd2 < 0) 395 if (fd2 < 0)
388 error(1, errno, "failed to create socket 2"); 396 error(1, errno, "failed to create socket 2");
397 if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
398 error(1, errno, "failed to set SO_REUSEPORT on socket 1");
399 if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
400 error(1, errno, "failed to set SO_REUSEPORT on socket 2");
389 401
390 attach_ebpf(fd1, 10); 402 attach_ebpf(fd1, 10);
391 attach_cbpf(fd2, 10); 403 attach_cbpf(fd2, 10);
@@ -394,6 +406,32 @@ static void test_filter_without_bind(void)
394 close(fd2); 406 close(fd2);
395} 407}
396 408
409void enable_fastopen(void)
410{
411 int fd = open("/proc/sys/net/ipv4/tcp_fastopen", 0);
412 int rw_mask = 3; /* bit 1: client side; bit-2 server side */
413 int val, size;
414 char buf[16];
415
416 if (fd < 0)
417 error(1, errno, "Unable to open tcp_fastopen sysctl");
418 if (read(fd, buf, sizeof(buf)) <= 0)
419 error(1, errno, "Unable to read tcp_fastopen sysctl");
420 val = atoi(buf);
421 close(fd);
422
423 if ((val & rw_mask) != rw_mask) {
424 fd = open("/proc/sys/net/ipv4/tcp_fastopen", O_RDWR);
425 if (fd < 0)
426 error(1, errno,
427 "Unable to open tcp_fastopen sysctl for writing");
428 val |= rw_mask;
429 size = snprintf(buf, 16, "%d", val);
430 if (write(fd, buf, size) <= 0)
431 error(1, errno, "Unable to write tcp_fastopen sysctl");
432 close(fd);
433 }
434}
397 435
398int main(void) 436int main(void)
399{ 437{
@@ -506,6 +544,71 @@ int main(void)
506 .recv_port = 8007, 544 .recv_port = 8007,
507 .send_port_min = 9100}); 545 .send_port_min = 9100});
508 546
547 /* TCP fastopen is required for the TCP tests */
548 enable_fastopen();
549 fprintf(stderr, "---- IPv4 TCP ----\n");
550 test_reuseport_ebpf((struct test_params) {
551 .recv_family = AF_INET,
552 .send_family = AF_INET,
553 .protocol = SOCK_STREAM,
554 .recv_socks = 10,
555 .recv_port = 8008,
556 .send_port_min = 9120});
557 test_reuseport_cbpf((struct test_params) {
558 .recv_family = AF_INET,
559 .send_family = AF_INET,
560 .protocol = SOCK_STREAM,
561 .recv_socks = 10,
562 .recv_port = 8009,
563 .send_port_min = 9160});
564 test_extra_filter((struct test_params) {
565 .recv_family = AF_INET,
566 .protocol = SOCK_STREAM,
567 .recv_port = 8010});
568 test_filter_no_reuseport((struct test_params) {
569 .recv_family = AF_INET,
570 .protocol = SOCK_STREAM,
571 .recv_port = 8011});
572
573 fprintf(stderr, "---- IPv6 TCP ----\n");
574 test_reuseport_ebpf((struct test_params) {
575 .recv_family = AF_INET6,
576 .send_family = AF_INET6,
577 .protocol = SOCK_STREAM,
578 .recv_socks = 10,
579 .recv_port = 8012,
580 .send_port_min = 9200});
581 test_reuseport_cbpf((struct test_params) {
582 .recv_family = AF_INET6,
583 .send_family = AF_INET6,
584 .protocol = SOCK_STREAM,
585 .recv_socks = 10,
586 .recv_port = 8013,
587 .send_port_min = 9240});
588 test_extra_filter((struct test_params) {
589 .recv_family = AF_INET6,
590 .protocol = SOCK_STREAM,
591 .recv_port = 8014});
592 test_filter_no_reuseport((struct test_params) {
593 .recv_family = AF_INET6,
594 .protocol = SOCK_STREAM,
595 .recv_port = 8015});
596
597 fprintf(stderr, "---- IPv6 TCP w/ mapped IPv4 ----\n");
598 test_reuseport_ebpf((struct test_params) {
599 .recv_family = AF_INET6,
600 .send_family = AF_INET,
601 .protocol = SOCK_STREAM,
602 .recv_socks = 10,
603 .recv_port = 8016,
604 .send_port_min = 9320});
605 test_reuseport_cbpf((struct test_params) {
606 .recv_family = AF_INET6,
607 .send_family = AF_INET,
608 .protocol = SOCK_STREAM,
609 .recv_socks = 10,
610 .recv_port = 8017,
611 .send_port_min = 9360});
509 612
510 test_filter_without_bind(); 613 test_filter_without_bind();
511 614
diff --git a/tools/testing/selftests/net/reuseport_bpf_cpu.c b/tools/testing/selftests/net/reuseport_bpf_cpu.c
new file mode 100644
index 000000000000..b23d6f54de7b
--- /dev/null
+++ b/tools/testing/selftests/net/reuseport_bpf_cpu.c
@@ -0,0 +1,258 @@
1/*
2 * Test functionality of BPF filters with SO_REUSEPORT. This program creates
3 * an SO_REUSEPORT receiver group containing one socket per CPU core. It then
4 * creates a BPF program that will select a socket from this group based
5 * on the core id that receives the packet. The sending code artificially
6 * moves itself to run on different core ids and sends one message from
7 * each core. Since these packets are delivered over loopback, they should
8 * arrive on the same core that sent them. The receiving code then ensures
9 * that the packet was received on the socket for the corresponding core id.
10 * This entire process is done for several different core id permutations
11 * and for each IPv4/IPv6 and TCP/UDP combination.
12 */
13
14#define _GNU_SOURCE
15
16#include <arpa/inet.h>
17#include <errno.h>
18#include <error.h>
19#include <linux/filter.h>
20#include <linux/in.h>
21#include <linux/unistd.h>
22#include <sched.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <sys/epoll.h>
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <unistd.h>
30
31static const int PORT = 8888;
32
33static void build_rcv_group(int *rcv_fd, size_t len, int family, int proto)
34{
35 struct sockaddr_storage addr;
36 struct sockaddr_in *addr4;
37 struct sockaddr_in6 *addr6;
38 size_t i;
39 int opt;
40
41 switch (family) {
42 case AF_INET:
43 addr4 = (struct sockaddr_in *)&addr;
44 addr4->sin_family = AF_INET;
45 addr4->sin_addr.s_addr = htonl(INADDR_ANY);
46 addr4->sin_port = htons(PORT);
47 break;
48 case AF_INET6:
49 addr6 = (struct sockaddr_in6 *)&addr;
50 addr6->sin6_family = AF_INET6;
51 addr6->sin6_addr = in6addr_any;
52 addr6->sin6_port = htons(PORT);
53 break;
54 default:
55 error(1, 0, "Unsupported family %d", family);
56 }
57
58 for (i = 0; i < len; ++i) {
59 rcv_fd[i] = socket(family, proto, 0);
60 if (rcv_fd[i] < 0)
61 error(1, errno, "failed to create receive socket");
62
63 opt = 1;
64 if (setsockopt(rcv_fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
65 sizeof(opt)))
66 error(1, errno, "failed to set SO_REUSEPORT");
67
68 if (bind(rcv_fd[i], (struct sockaddr *)&addr, sizeof(addr)))
69 error(1, errno, "failed to bind receive socket");
70
71 if (proto == SOCK_STREAM && listen(rcv_fd[i], len * 10))
72 error(1, errno, "failed to listen on receive port");
73 }
74}
75
76static void attach_bpf(int fd)
77{
78 struct sock_filter code[] = {
79 /* A = raw_smp_processor_id() */
80 { BPF_LD | BPF_W | BPF_ABS, 0, 0, SKF_AD_OFF + SKF_AD_CPU },
81 /* return A */
82 { BPF_RET | BPF_A, 0, 0, 0 },
83 };
84 struct sock_fprog p = {
85 .len = 2,
86 .filter = code,
87 };
88
89 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &p, sizeof(p)))
90 error(1, errno, "failed to set SO_ATTACH_REUSEPORT_CBPF");
91}
92
93static void send_from_cpu(int cpu_id, int family, int proto)
94{
95 struct sockaddr_storage saddr, daddr;
96 struct sockaddr_in *saddr4, *daddr4;
97 struct sockaddr_in6 *saddr6, *daddr6;
98 cpu_set_t cpu_set;
99 int fd;
100
101 switch (family) {
102 case AF_INET:
103 saddr4 = (struct sockaddr_in *)&saddr;
104 saddr4->sin_family = AF_INET;
105 saddr4->sin_addr.s_addr = htonl(INADDR_ANY);
106 saddr4->sin_port = 0;
107
108 daddr4 = (struct sockaddr_in *)&daddr;
109 daddr4->sin_family = AF_INET;
110 daddr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
111 daddr4->sin_port = htons(PORT);
112 break;
113 case AF_INET6:
114 saddr6 = (struct sockaddr_in6 *)&saddr;
115 saddr6->sin6_family = AF_INET6;
116 saddr6->sin6_addr = in6addr_any;
117 saddr6->sin6_port = 0;
118
119 daddr6 = (struct sockaddr_in6 *)&daddr;
120 daddr6->sin6_family = AF_INET6;
121 daddr6->sin6_addr = in6addr_loopback;
122 daddr6->sin6_port = htons(PORT);
123 break;
124 default:
125 error(1, 0, "Unsupported family %d", family);
126 }
127
128 memset(&cpu_set, 0, sizeof(cpu_set));
129 CPU_SET(cpu_id, &cpu_set);
130 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0)
131 error(1, errno, "failed to pin to cpu");
132
133 fd = socket(family, proto, 0);
134 if (fd < 0)
135 error(1, errno, "failed to create send socket");
136
137 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)))
138 error(1, errno, "failed to bind send socket");
139
140 if (connect(fd, (struct sockaddr *)&daddr, sizeof(daddr)))
141 error(1, errno, "failed to connect send socket");
142
143 if (send(fd, "a", 1, 0) < 0)
144 error(1, errno, "failed to send message");
145
146 close(fd);
147}
148
149static
150void receive_on_cpu(int *rcv_fd, int len, int epfd, int cpu_id, int proto)
151{
152 struct epoll_event ev;
153 int i, fd;
154 char buf[8];
155
156 i = epoll_wait(epfd, &ev, 1, -1);
157 if (i < 0)
158 error(1, errno, "epoll_wait failed");
159
160 if (proto == SOCK_STREAM) {
161 fd = accept(ev.data.fd, NULL, NULL);
162 if (fd < 0)
163 error(1, errno, "failed to accept");
164 i = recv(fd, buf, sizeof(buf), 0);
165 close(fd);
166 } else {
167 i = recv(ev.data.fd, buf, sizeof(buf), 0);
168 }
169
170 if (i < 0)
171 error(1, errno, "failed to recv");
172
173 for (i = 0; i < len; ++i)
174 if (ev.data.fd == rcv_fd[i])
175 break;
176 if (i == len)
177 error(1, 0, "failed to find socket");
178 fprintf(stderr, "send cpu %d, receive socket %d\n", cpu_id, i);
179 if (cpu_id != i)
180 error(1, 0, "cpu id/receive socket mismatch");
181}
182
183static void test(int *rcv_fd, int len, int family, int proto)
184{
185 struct epoll_event ev;
186 int epfd, cpu;
187
188 build_rcv_group(rcv_fd, len, family, proto);
189 attach_bpf(rcv_fd[0]);
190
191 epfd = epoll_create(1);
192 if (epfd < 0)
193 error(1, errno, "failed to create epoll");
194 for (cpu = 0; cpu < len; ++cpu) {
195 ev.events = EPOLLIN;
196 ev.data.fd = rcv_fd[cpu];
197 if (epoll_ctl(epfd, EPOLL_CTL_ADD, rcv_fd[cpu], &ev))
198 error(1, errno, "failed to register sock epoll");
199 }
200
201 /* Forward iterate */
202 for (cpu = 0; cpu < len; ++cpu) {
203 send_from_cpu(cpu, family, proto);
204 receive_on_cpu(rcv_fd, len, epfd, cpu, proto);
205 }
206
207 /* Reverse iterate */
208 for (cpu = len - 1; cpu >= 0; --cpu) {
209 send_from_cpu(cpu, family, proto);
210 receive_on_cpu(rcv_fd, len, epfd, cpu, proto);
211 }
212
213 /* Even cores */
214 for (cpu = 0; cpu < len; cpu += 2) {
215 send_from_cpu(cpu, family, proto);
216 receive_on_cpu(rcv_fd, len, epfd, cpu, proto);
217 }
218
219 /* Odd cores */
220 for (cpu = 1; cpu < len; cpu += 2) {
221 send_from_cpu(cpu, family, proto);
222 receive_on_cpu(rcv_fd, len, epfd, cpu, proto);
223 }
224
225 close(epfd);
226 for (cpu = 0; cpu < len; ++cpu)
227 close(rcv_fd[cpu]);
228}
229
230int main(void)
231{
232 int *rcv_fd, cpus;
233
234 cpus = sysconf(_SC_NPROCESSORS_ONLN);
235 if (cpus <= 0)
236 error(1, errno, "failed counting cpus");
237
238 rcv_fd = calloc(cpus, sizeof(int));
239 if (!rcv_fd)
240 error(1, 0, "failed to allocate array");
241
242 fprintf(stderr, "---- IPv4 UDP ----\n");
243 test(rcv_fd, cpus, AF_INET, SOCK_DGRAM);
244
245 fprintf(stderr, "---- IPv6 UDP ----\n");
246 test(rcv_fd, cpus, AF_INET6, SOCK_DGRAM);
247
248 fprintf(stderr, "---- IPv4 TCP ----\n");
249 test(rcv_fd, cpus, AF_INET, SOCK_STREAM);
250
251 fprintf(stderr, "---- IPv6 TCP ----\n");
252 test(rcv_fd, cpus, AF_INET6, SOCK_STREAM);
253
254 free(rcv_fd);
255
256 fprintf(stderr, "SUCCESS\n");
257 return 0;
258}