1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/socket.h>
6 #include <sys/ioctl.h>
7 #include <sys/select.h>
8 #include <netinet/in.h>
9 #include <arpa/inet.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <sys/ioctl.h>
14 #include <stdbool.h>
15 #include <signal.h>
16 #include <fcntl.h>
17 #include <sys/wait.h>
18 #include <time.h>
19 #include <sched.h>
20 
21 #include <sys/time.h>
22 #include <sys/resource.h>
23 #include <sys/types.h>
24 #include <sys/sendfile.h>
25 
26 #include <linux/netlink.h>
27 #include <linux/socket.h>
28 #include <linux/sock_diag.h>
29 #include <linux/bpf.h>
30 #include <linux/if_link.h>
31 #include <linux/tls.h>
32 #include <assert.h>
33 #include <libgen.h>
34 
35 #include <getopt.h>
36 
37 #include <bpf/bpf.h>
38 #include <bpf/libbpf.h>
39 
40 #include "bpf_util.h"
41 #include "bpf_rlimit.h"
42 #include "cgroup_helpers.h"
43 
44 int running;
45 static void running_handler(int a);
46 
47 #ifndef TCP_ULP
48 # define TCP_ULP 31
49 #endif
50 #ifndef SOL_TLS
51 # define SOL_TLS 282
52 #endif
53 
54 /* randomly selected ports for testing on lo */
55 #define S1_PORT 10000
56 #define S2_PORT 10001
57 
58 #define BPF_SOCKMAP_FILENAME "test_sockmap_kern.o"
59 #define BPF_SOCKHASH_FILENAME "test_sockhash_kern.o"
60 #define CG_PATH "/sockmap"
61 
62 /* global sockets */
63 int s1, s2, c1, c2, p1, p2;
64 int test_cnt;
65 int passed;
66 int failed;
67 int map_fd[8];
68 struct bpf_map *maps[8];
69 int prog_fd[11];
70 
71 int txmsg_pass;
72 int txmsg_noisy;
73 int txmsg_redir;
74 int txmsg_redir_noisy;
75 int txmsg_drop;
76 int txmsg_apply;
77 int txmsg_cork;
78 int txmsg_start;
79 int txmsg_end;
80 int txmsg_start_push;
81 int txmsg_end_push;
82 int txmsg_start_pop;
83 int txmsg_pop;
84 int txmsg_ingress;
85 int txmsg_skb;
86 int ktls;
87 int peek_flag;
88 
89 static const struct option long_options[] = {
90 	{"help",	no_argument,		NULL, 'h' },
91 	{"cgroup",	required_argument,	NULL, 'c' },
92 	{"rate",	required_argument,	NULL, 'r' },
93 	{"verbose",	no_argument,		NULL, 'v' },
94 	{"iov_count",	required_argument,	NULL, 'i' },
95 	{"length",	required_argument,	NULL, 'l' },
96 	{"test",	required_argument,	NULL, 't' },
97 	{"data_test",   no_argument,		NULL, 'd' },
98 	{"txmsg",		no_argument,	&txmsg_pass,  1  },
99 	{"txmsg_noisy",		no_argument,	&txmsg_noisy, 1  },
100 	{"txmsg_redir",		no_argument,	&txmsg_redir, 1  },
101 	{"txmsg_redir_noisy",	no_argument,	&txmsg_redir_noisy, 1},
102 	{"txmsg_drop",		no_argument,	&txmsg_drop, 1 },
103 	{"txmsg_apply",	required_argument,	NULL, 'a'},
104 	{"txmsg_cork",	required_argument,	NULL, 'k'},
105 	{"txmsg_start", required_argument,	NULL, 's'},
106 	{"txmsg_end",	required_argument,	NULL, 'e'},
107 	{"txmsg_start_push", required_argument,	NULL, 'p'},
108 	{"txmsg_end_push",   required_argument,	NULL, 'q'},
109 	{"txmsg_start_pop",  required_argument,	NULL, 'w'},
110 	{"txmsg_pop",	     required_argument,	NULL, 'x'},
111 	{"txmsg_ingress", no_argument,		&txmsg_ingress, 1 },
112 	{"txmsg_skb", no_argument,		&txmsg_skb, 1 },
113 	{"ktls", no_argument,			&ktls, 1 },
114 	{"peek", no_argument,			&peek_flag, 1 },
115 	{0, 0, NULL, 0 }
116 };
117 
118 static void usage(char *argv[])
119 {
120 	int i;
121 
122 	printf(" Usage: %s --cgroup <cgroup_path>\n", argv[0]);
123 	printf(" options:\n");
124 	for (i = 0; long_options[i].name != 0; i++) {
125 		printf(" --%-12s", long_options[i].name);
126 		if (long_options[i].flag != NULL)
127 			printf(" flag (internal value:%d)\n",
128 				*long_options[i].flag);
129 		else
130 			printf(" -%c\n", long_options[i].val);
131 	}
132 	printf("\n");
133 }
134 
135 char *sock_to_string(int s)
136 {
137 	if (s == c1)
138 		return "client1";
139 	else if (s == c2)
140 		return "client2";
141 	else if (s == s1)
142 		return "server1";
143 	else if (s == s2)
144 		return "server2";
145 	else if (s == p1)
146 		return "peer1";
147 	else if (s == p2)
148 		return "peer2";
149 	else
150 		return "unknown";
151 }
152 
153 static int sockmap_init_ktls(int verbose, int s)
154 {
155 	struct tls12_crypto_info_aes_gcm_128 tls_tx = {
156 		.info = {
157 			.version     = TLS_1_2_VERSION,
158 			.cipher_type = TLS_CIPHER_AES_GCM_128,
159 		},
160 	};
161 	struct tls12_crypto_info_aes_gcm_128 tls_rx = {
162 		.info = {
163 			.version     = TLS_1_2_VERSION,
164 			.cipher_type = TLS_CIPHER_AES_GCM_128,
165 		},
166 	};
167 	int so_buf = 6553500;
168 	int err;
169 
170 	err = setsockopt(s, 6, TCP_ULP, "tls", sizeof("tls"));
171 	if (err) {
172 		fprintf(stderr, "setsockopt: TCP_ULP(%s) failed with error %i\n", sock_to_string(s), err);
173 		return -EINVAL;
174 	}
175 	err = setsockopt(s, SOL_TLS, TLS_TX, (void *)&tls_tx, sizeof(tls_tx));
176 	if (err) {
177 		fprintf(stderr, "setsockopt: TLS_TX(%s) failed with error %i\n", sock_to_string(s), err);
178 		return -EINVAL;
179 	}
180 	err = setsockopt(s, SOL_TLS, TLS_RX, (void *)&tls_rx, sizeof(tls_rx));
181 	if (err) {
182 		fprintf(stderr, "setsockopt: TLS_RX(%s) failed with error %i\n", sock_to_string(s), err);
183 		return -EINVAL;
184 	}
185 	err = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &so_buf, sizeof(so_buf));
186 	if (err) {
187 		fprintf(stderr, "setsockopt: (%s) failed sndbuf with error %i\n", sock_to_string(s), err);
188 		return -EINVAL;
189 	}
190 	err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &so_buf, sizeof(so_buf));
191 	if (err) {
192 		fprintf(stderr, "setsockopt: (%s) failed rcvbuf with error %i\n", sock_to_string(s), err);
193 		return -EINVAL;
194 	}
195 
196 	if (verbose)
197 		fprintf(stdout, "socket(%s) kTLS enabled\n", sock_to_string(s));
198 	return 0;
199 }
200 static int sockmap_init_sockets(int verbose)
201 {
202 	int i, err, one = 1;
203 	struct sockaddr_in addr;
204 	int *fds[4] = {&s1, &s2, &c1, &c2};
205 
206 	s1 = s2 = p1 = p2 = c1 = c2 = 0;
207 
208 	/* Init sockets */
209 	for (i = 0; i < 4; i++) {
210 		*fds[i] = socket(AF_INET, SOCK_STREAM, 0);
211 		if (*fds[i] < 0) {
212 			perror("socket s1 failed()");
213 			return errno;
214 		}
215 	}
216 
217 	/* Allow reuse */
218 	for (i = 0; i < 2; i++) {
219 		err = setsockopt(*fds[i], SOL_SOCKET, SO_REUSEADDR,
220 				 (char *)&one, sizeof(one));
221 		if (err) {
222 			perror("setsockopt failed()");
223 			return errno;
224 		}
225 	}
226 
227 	/* Non-blocking sockets */
228 	for (i = 0; i < 2; i++) {
229 		err = ioctl(*fds[i], FIONBIO, (char *)&one);
230 		if (err < 0) {
231 			perror("ioctl s1 failed()");
232 			return errno;
233 		}
234 	}
235 
236 	/* Bind server sockets */
237 	memset(&addr, 0, sizeof(struct sockaddr_in));
238 	addr.sin_family = AF_INET;
239 	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
240 
241 	addr.sin_port = htons(S1_PORT);
242 	err = bind(s1, (struct sockaddr *)&addr, sizeof(addr));
243 	if (err < 0) {
244 		perror("bind s1 failed()\n");
245 		return errno;
246 	}
247 
248 	addr.sin_port = htons(S2_PORT);
249 	err = bind(s2, (struct sockaddr *)&addr, sizeof(addr));
250 	if (err < 0) {
251 		perror("bind s2 failed()\n");
252 		return errno;
253 	}
254 
255 	/* Listen server sockets */
256 	addr.sin_port = htons(S1_PORT);
257 	err = listen(s1, 32);
258 	if (err < 0) {
259 		perror("listen s1 failed()\n");
260 		return errno;
261 	}
262 
263 	addr.sin_port = htons(S2_PORT);
264 	err = listen(s2, 32);
265 	if (err < 0) {
266 		perror("listen s1 failed()\n");
267 		return errno;
268 	}
269 
270 	/* Initiate Connect */
271 	addr.sin_port = htons(S1_PORT);
272 	err = connect(c1, (struct sockaddr *)&addr, sizeof(addr));
273 	if (err < 0 && errno != EINPROGRESS) {
274 		perror("connect c1 failed()\n");
275 		return errno;
276 	}
277 
278 	addr.sin_port = htons(S2_PORT);
279 	err = connect(c2, (struct sockaddr *)&addr, sizeof(addr));
280 	if (err < 0 && errno != EINPROGRESS) {
281 		perror("connect c2 failed()\n");
282 		return errno;
283 	} else if (err < 0) {
284 		err = 0;
285 	}
286 
287 	/* Accept Connecrtions */
288 	p1 = accept(s1, NULL, NULL);
289 	if (p1 < 0) {
290 		perror("accept s1 failed()\n");
291 		return errno;
292 	}
293 
294 	p2 = accept(s2, NULL, NULL);
295 	if (p2 < 0) {
296 		perror("accept s1 failed()\n");
297 		return errno;
298 	}
299 
300 	if (verbose) {
301 		printf("connected sockets: c1 <-> p1, c2 <-> p2\n");
302 		printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n",
303 			c1, s1, c2, s2);
304 	}
305 	return 0;
306 }
307 
308 struct msg_stats {
309 	size_t bytes_sent;
310 	size_t bytes_recvd;
311 	struct timespec start;
312 	struct timespec end;
313 };
314 
315 struct sockmap_options {
316 	int verbose;
317 	bool base;
318 	bool sendpage;
319 	bool data_test;
320 	bool drop_expected;
321 	int iov_count;
322 	int iov_length;
323 	int rate;
324 };
325 
326 static int msg_loop_sendpage(int fd, int iov_length, int cnt,
327 			     struct msg_stats *s,
328 			     struct sockmap_options *opt)
329 {
330 	bool drop = opt->drop_expected;
331 	unsigned char k = 0;
332 	FILE *file;
333 	int i, fp;
334 
335 	file = fopen(".sendpage_tst.tmp", "w+");
336 	for (i = 0; i < iov_length * cnt; i++, k++)
337 		fwrite(&k, sizeof(char), 1, file);
338 	fflush(file);
339 	fseek(file, 0, SEEK_SET);
340 	fclose(file);
341 
342 	fp = open(".sendpage_tst.tmp", O_RDONLY);
343 	clock_gettime(CLOCK_MONOTONIC, &s->start);
344 	for (i = 0; i < cnt; i++) {
345 		int sent = sendfile(fd, fp, NULL, iov_length);
346 
347 		if (!drop && sent < 0) {
348 			perror("send loop error:");
349 			close(fp);
350 			return sent;
351 		} else if (drop && sent >= 0) {
352 			printf("sendpage loop error expected: %i\n", sent);
353 			close(fp);
354 			return -EIO;
355 		}
356 
357 		if (sent > 0)
358 			s->bytes_sent += sent;
359 	}
360 	clock_gettime(CLOCK_MONOTONIC, &s->end);
361 	close(fp);
362 	return 0;
363 }
364 
365 static void msg_free_iov(struct msghdr *msg)
366 {
367 	int i;
368 
369 	for (i = 0; i < msg->msg_iovlen; i++)
370 		free(msg->msg_iov[i].iov_base);
371 	free(msg->msg_iov);
372 	msg->msg_iov = NULL;
373 	msg->msg_iovlen = 0;
374 }
375 
376 static int msg_alloc_iov(struct msghdr *msg,
377 			 int iov_count, int iov_length,
378 			 bool data, bool xmit)
379 {
380 	unsigned char k = 0;
381 	struct iovec *iov;
382 	int i;
383 
384 	iov = calloc(iov_count, sizeof(struct iovec));
385 	if (!iov)
386 		return errno;
387 
388 	for (i = 0; i < iov_count; i++) {
389 		unsigned char *d = calloc(iov_length, sizeof(char));
390 
391 		if (!d) {
392 			fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count);
393 			goto unwind_iov;
394 		}
395 		iov[i].iov_base = d;
396 		iov[i].iov_len = iov_length;
397 
398 		if (data && xmit) {
399 			int j;
400 
401 			for (j = 0; j < iov_length; j++)
402 				d[j] = k++;
403 		}
404 	}
405 
406 	msg->msg_iov = iov;
407 	msg->msg_iovlen = iov_count;
408 
409 	return 0;
410 unwind_iov:
411 	for (i--; i >= 0 ; i--)
412 		free(msg->msg_iov[i].iov_base);
413 	return -ENOMEM;
414 }
415 
416 static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz)
417 {
418 	int i, j, bytes_cnt = 0;
419 	unsigned char k = 0;
420 
421 	for (i = 0; i < msg->msg_iovlen; i++) {
422 		unsigned char *d = msg->msg_iov[i].iov_base;
423 
424 		for (j = 0;
425 		     j < msg->msg_iov[i].iov_len && size; j++) {
426 			if (d[j] != k++) {
427 				fprintf(stderr,
428 					"detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
429 					i, j, d[j], k - 1, d[j+1], k);
430 				return -EIO;
431 			}
432 			bytes_cnt++;
433 			if (bytes_cnt == chunk_sz) {
434 				k = 0;
435 				bytes_cnt = 0;
436 			}
437 			size--;
438 		}
439 	}
440 	return 0;
441 }
442 
443 static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
444 		    struct msg_stats *s, bool tx,
445 		    struct sockmap_options *opt)
446 {
447 	struct msghdr msg = {0}, msg_peek = {0};
448 	int err, i, flags = MSG_NOSIGNAL;
449 	bool drop = opt->drop_expected;
450 	bool data = opt->data_test;
451 
452 	err = msg_alloc_iov(&msg, iov_count, iov_length, data, tx);
453 	if (err)
454 		goto out_errno;
455 	if (peek_flag) {
456 		err = msg_alloc_iov(&msg_peek, iov_count, iov_length, data, tx);
457 		if (err)
458 			goto out_errno;
459 	}
460 
461 	if (tx) {
462 		clock_gettime(CLOCK_MONOTONIC, &s->start);
463 		for (i = 0; i < cnt; i++) {
464 			int sent = sendmsg(fd, &msg, flags);
465 
466 			if (!drop && sent < 0) {
467 				perror("send loop error:");
468 				goto out_errno;
469 			} else if (drop && sent >= 0) {
470 				printf("send loop error expected: %i\n", sent);
471 				errno = -EIO;
472 				goto out_errno;
473 			}
474 			if (sent > 0)
475 				s->bytes_sent += sent;
476 		}
477 		clock_gettime(CLOCK_MONOTONIC, &s->end);
478 	} else {
479 		int slct, recvp = 0, recv, max_fd = fd;
480 		float total_bytes, txmsg_pop_total;
481 		int fd_flags = O_NONBLOCK;
482 		struct timeval timeout;
483 		fd_set w;
484 
485 		fcntl(fd, fd_flags);
486 		/* Account for pop bytes noting each iteration of apply will
487 		 * call msg_pop_data helper so we need to account for this
488 		 * by calculating the number of apply iterations. Note user
489 		 * of the tool can create cases where no data is sent by
490 		 * manipulating pop/push/pull/etc. For example txmsg_apply 1
491 		 * with txmsg_pop 1 will try to apply 1B at a time but each
492 		 * iteration will then pop 1B so no data will ever be sent.
493 		 * This is really only useful for testing edge cases in code
494 		 * paths.
495 		 */
496 		total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
497 		txmsg_pop_total = txmsg_pop;
498 		if (txmsg_apply)
499 			txmsg_pop_total *= (total_bytes / txmsg_apply);
500 		total_bytes -= txmsg_pop_total;
501 		err = clock_gettime(CLOCK_MONOTONIC, &s->start);
502 		if (err < 0)
503 			perror("recv start time: ");
504 		while (s->bytes_recvd < total_bytes) {
505 			if (txmsg_cork) {
506 				timeout.tv_sec = 0;
507 				timeout.tv_usec = 300000;
508 			} else {
509 				timeout.tv_sec = 3;
510 				timeout.tv_usec = 0;
511 			}
512 
513 			/* FD sets */
514 			FD_ZERO(&w);
515 			FD_SET(fd, &w);
516 
517 			slct = select(max_fd + 1, &w, NULL, NULL, &timeout);
518 			if (slct == -1) {
519 				perror("select()");
520 				clock_gettime(CLOCK_MONOTONIC, &s->end);
521 				goto out_errno;
522 			} else if (!slct) {
523 				if (opt->verbose)
524 					fprintf(stderr, "unexpected timeout: recved %zu/%f pop_total %f\n", s->bytes_recvd, total_bytes, txmsg_pop_total);
525 				errno = -EIO;
526 				clock_gettime(CLOCK_MONOTONIC, &s->end);
527 				goto out_errno;
528 			}
529 
530 			errno = 0;
531 			if (peek_flag) {
532 				flags |= MSG_PEEK;
533 				recvp = recvmsg(fd, &msg_peek, flags);
534 				if (recvp < 0) {
535 					if (errno != EWOULDBLOCK) {
536 						clock_gettime(CLOCK_MONOTONIC, &s->end);
537 						goto out_errno;
538 					}
539 				}
540 				flags = 0;
541 			}
542 
543 			recv = recvmsg(fd, &msg, flags);
544 			if (recv < 0) {
545 				if (errno != EWOULDBLOCK) {
546 					clock_gettime(CLOCK_MONOTONIC, &s->end);
547 					perror("recv failed()\n");
548 					goto out_errno;
549 				}
550 			}
551 
552 			s->bytes_recvd += recv;
553 
554 			if (data) {
555 				int chunk_sz = opt->sendpage ?
556 						iov_length * cnt :
557 						iov_length * iov_count;
558 
559 				errno = msg_verify_data(&msg, recv, chunk_sz);
560 				if (errno) {
561 					perror("data verify msg failed\n");
562 					goto out_errno;
563 				}
564 				if (recvp) {
565 					errno = msg_verify_data(&msg_peek,
566 								recvp,
567 								chunk_sz);
568 					if (errno) {
569 						perror("data verify msg_peek failed\n");
570 						goto out_errno;
571 					}
572 				}
573 			}
574 		}
575 		clock_gettime(CLOCK_MONOTONIC, &s->end);
576 	}
577 
578 	msg_free_iov(&msg);
579 	msg_free_iov(&msg_peek);
580 	return err;
581 out_errno:
582 	msg_free_iov(&msg);
583 	msg_free_iov(&msg_peek);
584 	return errno;
585 }
586 
587 static float giga = 1000000000;
588 
589 static inline float sentBps(struct msg_stats s)
590 {
591 	return s.bytes_sent / (s.end.tv_sec - s.start.tv_sec);
592 }
593 
594 static inline float recvdBps(struct msg_stats s)
595 {
596 	return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec);
597 }
598 
599 static int sendmsg_test(struct sockmap_options *opt)
600 {
601 	float sent_Bps = 0, recvd_Bps = 0;
602 	int rx_fd, txpid, rxpid, err = 0;
603 	struct msg_stats s = {0};
604 	int iov_count = opt->iov_count;
605 	int iov_buf = opt->iov_length;
606 	int rx_status, tx_status;
607 	int cnt = opt->rate;
608 
609 	errno = 0;
610 
611 	if (opt->base)
612 		rx_fd = p1;
613 	else
614 		rx_fd = p2;
615 
616 	if (ktls) {
617 		/* Redirecting into non-TLS socket which sends into a TLS
618 		 * socket is not a valid test. So in this case lets not
619 		 * enable kTLS but still run the test.
620 		 */
621 		if (!txmsg_redir || (txmsg_redir && txmsg_ingress)) {
622 			err = sockmap_init_ktls(opt->verbose, rx_fd);
623 			if (err)
624 				return err;
625 		}
626 		err = sockmap_init_ktls(opt->verbose, c1);
627 		if (err)
628 			return err;
629 	}
630 
631 	rxpid = fork();
632 	if (rxpid == 0) {
633 		if (opt->drop_expected)
634 			exit(0);
635 
636 		if (opt->sendpage)
637 			iov_count = 1;
638 		err = msg_loop(rx_fd, iov_count, iov_buf,
639 			       cnt, &s, false, opt);
640 		if (opt->verbose)
641 			fprintf(stderr,
642 				"msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
643 				iov_count, iov_buf, cnt, err);
644 		if (s.end.tv_sec - s.start.tv_sec) {
645 			sent_Bps = sentBps(s);
646 			recvd_Bps = recvdBps(s);
647 		}
648 		if (opt->verbose)
649 			fprintf(stdout,
650 				"rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s %s\n",
651 				s.bytes_sent, sent_Bps, sent_Bps/giga,
652 				s.bytes_recvd, recvd_Bps, recvd_Bps/giga,
653 				peek_flag ? "(peek_msg)" : "");
654 		if (err && txmsg_cork)
655 			err = 0;
656 		exit(err ? 1 : 0);
657 	} else if (rxpid == -1) {
658 		perror("msg_loop_rx: ");
659 		return errno;
660 	}
661 
662 	txpid = fork();
663 	if (txpid == 0) {
664 		if (opt->sendpage)
665 			err = msg_loop_sendpage(c1, iov_buf, cnt, &s, opt);
666 		else
667 			err = msg_loop(c1, iov_count, iov_buf,
668 				       cnt, &s, true, opt);
669 
670 		if (err)
671 			fprintf(stderr,
672 				"msg_loop_tx: iov_count %i iov_buf %i cnt %i err %i\n",
673 				iov_count, iov_buf, cnt, err);
674 		if (s.end.tv_sec - s.start.tv_sec) {
675 			sent_Bps = sentBps(s);
676 			recvd_Bps = recvdBps(s);
677 		}
678 		if (opt->verbose)
679 			fprintf(stdout,
680 				"tx_sendmsg: TX: %zuB %fB/s %f GB/s RX: %zuB %fB/s %fGB/s\n",
681 				s.bytes_sent, sent_Bps, sent_Bps/giga,
682 				s.bytes_recvd, recvd_Bps, recvd_Bps/giga);
683 		exit(err ? 1 : 0);
684 	} else if (txpid == -1) {
685 		perror("msg_loop_tx: ");
686 		return errno;
687 	}
688 
689 	assert(waitpid(rxpid, &rx_status, 0) == rxpid);
690 	assert(waitpid(txpid, &tx_status, 0) == txpid);
691 	if (WIFEXITED(rx_status)) {
692 		err = WEXITSTATUS(rx_status);
693 		if (err) {
694 			fprintf(stderr, "rx thread exited with err %d. ", err);
695 			goto out;
696 		}
697 	}
698 	if (WIFEXITED(tx_status)) {
699 		err = WEXITSTATUS(tx_status);
700 		if (err)
701 			fprintf(stderr, "tx thread exited with err %d. ", err);
702 	}
703 out:
704 	return err;
705 }
706 
707 static int forever_ping_pong(int rate, struct sockmap_options *opt)
708 {
709 	struct timeval timeout;
710 	char buf[1024] = {0};
711 	int sc;
712 
713 	timeout.tv_sec = 10;
714 	timeout.tv_usec = 0;
715 
716 	/* Ping/Pong data from client to server */
717 	sc = send(c1, buf, sizeof(buf), 0);
718 	if (sc < 0) {
719 		perror("send failed()\n");
720 		return sc;
721 	}
722 
723 	do {
724 		int s, rc, i, max_fd = p2;
725 		fd_set w;
726 
727 		/* FD sets */
728 		FD_ZERO(&w);
729 		FD_SET(c1, &w);
730 		FD_SET(c2, &w);
731 		FD_SET(p1, &w);
732 		FD_SET(p2, &w);
733 
734 		s = select(max_fd + 1, &w, NULL, NULL, &timeout);
735 		if (s == -1) {
736 			perror("select()");
737 			break;
738 		} else if (!s) {
739 			fprintf(stderr, "unexpected timeout\n");
740 			break;
741 		}
742 
743 		for (i = 0; i <= max_fd && s > 0; ++i) {
744 			if (!FD_ISSET(i, &w))
745 				continue;
746 
747 			s--;
748 
749 			rc = recv(i, buf, sizeof(buf), 0);
750 			if (rc < 0) {
751 				if (errno != EWOULDBLOCK) {
752 					perror("recv failed()\n");
753 					return rc;
754 				}
755 			}
756 
757 			if (rc == 0) {
758 				close(i);
759 				break;
760 			}
761 
762 			sc = send(i, buf, rc, 0);
763 			if (sc < 0) {
764 				perror("send failed()\n");
765 				return sc;
766 			}
767 		}
768 
769 		if (rate)
770 			sleep(rate);
771 
772 		if (opt->verbose) {
773 			printf(".");
774 			fflush(stdout);
775 
776 		}
777 	} while (running);
778 
779 	return 0;
780 }
781 
782 enum {
783 	PING_PONG,
784 	SENDMSG,
785 	BASE,
786 	BASE_SENDPAGE,
787 	SENDPAGE,
788 };
789 
790 static int run_options(struct sockmap_options *options, int cg_fd,  int test)
791 {
792 	int i, key, next_key, err, tx_prog_fd = -1, zero = 0;
793 
794 	/* If base test skip BPF setup */
795 	if (test == BASE || test == BASE_SENDPAGE)
796 		goto run;
797 
798 	/* Attach programs to sockmap */
799 	err = bpf_prog_attach(prog_fd[0], map_fd[0],
800 				BPF_SK_SKB_STREAM_PARSER, 0);
801 	if (err) {
802 		fprintf(stderr,
803 			"ERROR: bpf_prog_attach (sockmap %i->%i): %d (%s)\n",
804 			prog_fd[0], map_fd[0], err, strerror(errno));
805 		return err;
806 	}
807 
808 	err = bpf_prog_attach(prog_fd[1], map_fd[0],
809 				BPF_SK_SKB_STREAM_VERDICT, 0);
810 	if (err) {
811 		fprintf(stderr, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n",
812 			err, strerror(errno));
813 		return err;
814 	}
815 
816 	/* Attach to cgroups */
817 	err = bpf_prog_attach(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS, 0);
818 	if (err) {
819 		fprintf(stderr, "ERROR: bpf_prog_attach (groups): %d (%s)\n",
820 			err, strerror(errno));
821 		return err;
822 	}
823 
824 run:
825 	err = sockmap_init_sockets(options->verbose);
826 	if (err) {
827 		fprintf(stderr, "ERROR: test socket failed: %d\n", err);
828 		goto out;
829 	}
830 
831 	/* Attach txmsg program to sockmap */
832 	if (txmsg_pass)
833 		tx_prog_fd = prog_fd[3];
834 	else if (txmsg_noisy)
835 		tx_prog_fd = prog_fd[4];
836 	else if (txmsg_redir)
837 		tx_prog_fd = prog_fd[5];
838 	else if (txmsg_redir_noisy)
839 		tx_prog_fd = prog_fd[6];
840 	else if (txmsg_drop)
841 		tx_prog_fd = prog_fd[9];
842 	/* apply and cork must be last */
843 	else if (txmsg_apply)
844 		tx_prog_fd = prog_fd[7];
845 	else if (txmsg_cork)
846 		tx_prog_fd = prog_fd[8];
847 	else
848 		tx_prog_fd = 0;
849 
850 	if (tx_prog_fd) {
851 		int redir_fd, i = 0;
852 
853 		err = bpf_prog_attach(tx_prog_fd,
854 				      map_fd[1], BPF_SK_MSG_VERDICT, 0);
855 		if (err) {
856 			fprintf(stderr,
857 				"ERROR: bpf_prog_attach (txmsg): %d (%s)\n",
858 				err, strerror(errno));
859 			goto out;
860 		}
861 
862 		err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY);
863 		if (err) {
864 			fprintf(stderr,
865 				"ERROR: bpf_map_update_elem (txmsg):  %d (%s\n",
866 				err, strerror(errno));
867 			goto out;
868 		}
869 
870 		if (txmsg_redir || txmsg_redir_noisy)
871 			redir_fd = c2;
872 		else
873 			redir_fd = c1;
874 
875 		err = bpf_map_update_elem(map_fd[2], &i, &redir_fd, BPF_ANY);
876 		if (err) {
877 			fprintf(stderr,
878 				"ERROR: bpf_map_update_elem (txmsg):  %d (%s\n",
879 				err, strerror(errno));
880 			goto out;
881 		}
882 
883 		if (txmsg_apply) {
884 			err = bpf_map_update_elem(map_fd[3],
885 						  &i, &txmsg_apply, BPF_ANY);
886 			if (err) {
887 				fprintf(stderr,
888 					"ERROR: bpf_map_update_elem (apply_bytes):  %d (%s\n",
889 					err, strerror(errno));
890 				goto out;
891 			}
892 		}
893 
894 		if (txmsg_cork) {
895 			err = bpf_map_update_elem(map_fd[4],
896 						  &i, &txmsg_cork, BPF_ANY);
897 			if (err) {
898 				fprintf(stderr,
899 					"ERROR: bpf_map_update_elem (cork_bytes):  %d (%s\n",
900 					err, strerror(errno));
901 				goto out;
902 			}
903 		}
904 
905 		if (txmsg_start) {
906 			err = bpf_map_update_elem(map_fd[5],
907 						  &i, &txmsg_start, BPF_ANY);
908 			if (err) {
909 				fprintf(stderr,
910 					"ERROR: bpf_map_update_elem (txmsg_start):  %d (%s)\n",
911 					err, strerror(errno));
912 				goto out;
913 			}
914 		}
915 
916 		if (txmsg_end) {
917 			i = 1;
918 			err = bpf_map_update_elem(map_fd[5],
919 						  &i, &txmsg_end, BPF_ANY);
920 			if (err) {
921 				fprintf(stderr,
922 					"ERROR: bpf_map_update_elem (txmsg_end):  %d (%s)\n",
923 					err, strerror(errno));
924 				goto out;
925 			}
926 		}
927 
928 		if (txmsg_start_push) {
929 			i = 2;
930 			err = bpf_map_update_elem(map_fd[5],
931 						  &i, &txmsg_start_push, BPF_ANY);
932 			if (err) {
933 				fprintf(stderr,
934 					"ERROR: bpf_map_update_elem (txmsg_start_push):  %d (%s)\n",
935 					err, strerror(errno));
936 				goto out;
937 			}
938 		}
939 
940 		if (txmsg_end_push) {
941 			i = 3;
942 			err = bpf_map_update_elem(map_fd[5],
943 						  &i, &txmsg_end_push, BPF_ANY);
944 			if (err) {
945 				fprintf(stderr,
946 					"ERROR: bpf_map_update_elem %i@%i (txmsg_end_push):  %d (%s)\n",
947 					txmsg_end_push, i, err, strerror(errno));
948 				goto out;
949 			}
950 		}
951 
952 		if (txmsg_start_pop) {
953 			i = 4;
954 			err = bpf_map_update_elem(map_fd[5],
955 						  &i, &txmsg_start_pop, BPF_ANY);
956 			if (err) {
957 				fprintf(stderr,
958 					"ERROR: bpf_map_update_elem %i@%i (txmsg_start_pop):  %d (%s)\n",
959 					txmsg_start_pop, i, err, strerror(errno));
960 				goto out;
961 			}
962 		} else {
963 			i = 4;
964 			bpf_map_update_elem(map_fd[5],
965 						  &i, &txmsg_start_pop, BPF_ANY);
966 		}
967 
968 		if (txmsg_pop) {
969 			i = 5;
970 			err = bpf_map_update_elem(map_fd[5],
971 						  &i, &txmsg_pop, BPF_ANY);
972 			if (err) {
973 				fprintf(stderr,
974 					"ERROR: bpf_map_update_elem %i@%i (txmsg_pop):  %d (%s)\n",
975 					txmsg_pop, i, err, strerror(errno));
976 				goto out;
977 			}
978 		} else {
979 			i = 5;
980 			bpf_map_update_elem(map_fd[5],
981 					    &i, &txmsg_pop, BPF_ANY);
982 
983 		}
984 
985 		if (txmsg_ingress) {
986 			int in = BPF_F_INGRESS;
987 
988 			i = 0;
989 			err = bpf_map_update_elem(map_fd[6], &i, &in, BPF_ANY);
990 			if (err) {
991 				fprintf(stderr,
992 					"ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
993 					err, strerror(errno));
994 			}
995 			i = 1;
996 			err = bpf_map_update_elem(map_fd[1], &i, &p1, BPF_ANY);
997 			if (err) {
998 				fprintf(stderr,
999 					"ERROR: bpf_map_update_elem (p1 txmsg): %d (%s)\n",
1000 					err, strerror(errno));
1001 			}
1002 			err = bpf_map_update_elem(map_fd[2], &i, &p1, BPF_ANY);
1003 			if (err) {
1004 				fprintf(stderr,
1005 					"ERROR: bpf_map_update_elem (p1 redir): %d (%s)\n",
1006 					err, strerror(errno));
1007 			}
1008 
1009 			i = 2;
1010 			err = bpf_map_update_elem(map_fd[2], &i, &p2, BPF_ANY);
1011 			if (err) {
1012 				fprintf(stderr,
1013 					"ERROR: bpf_map_update_elem (p2 txmsg): %d (%s)\n",
1014 					err, strerror(errno));
1015 			}
1016 		}
1017 
1018 		if (txmsg_skb) {
1019 			int skb_fd = (test == SENDMSG || test == SENDPAGE) ?
1020 					p2 : p1;
1021 			int ingress = BPF_F_INGRESS;
1022 
1023 			i = 0;
1024 			err = bpf_map_update_elem(map_fd[7],
1025 						  &i, &ingress, BPF_ANY);
1026 			if (err) {
1027 				fprintf(stderr,
1028 					"ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
1029 					err, strerror(errno));
1030 			}
1031 
1032 			i = 3;
1033 			err = bpf_map_update_elem(map_fd[0],
1034 						  &i, &skb_fd, BPF_ANY);
1035 			if (err) {
1036 				fprintf(stderr,
1037 					"ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
1038 					err, strerror(errno));
1039 			}
1040 		}
1041 	}
1042 
1043 	if (txmsg_drop)
1044 		options->drop_expected = true;
1045 
1046 	if (test == PING_PONG)
1047 		err = forever_ping_pong(options->rate, options);
1048 	else if (test == SENDMSG) {
1049 		options->base = false;
1050 		options->sendpage = false;
1051 		err = sendmsg_test(options);
1052 	} else if (test == SENDPAGE) {
1053 		options->base = false;
1054 		options->sendpage = true;
1055 		err = sendmsg_test(options);
1056 	} else if (test == BASE) {
1057 		options->base = true;
1058 		options->sendpage = false;
1059 		err = sendmsg_test(options);
1060 	} else if (test == BASE_SENDPAGE) {
1061 		options->base = true;
1062 		options->sendpage = true;
1063 		err = sendmsg_test(options);
1064 	} else
1065 		fprintf(stderr, "unknown test\n");
1066 out:
1067 	/* Detatch and zero all the maps */
1068 	bpf_prog_detach2(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS);
1069 	bpf_prog_detach2(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER);
1070 	bpf_prog_detach2(prog_fd[1], map_fd[0], BPF_SK_SKB_STREAM_VERDICT);
1071 	if (tx_prog_fd >= 0)
1072 		bpf_prog_detach2(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT);
1073 
1074 	for (i = 0; i < 8; i++) {
1075 		key = next_key = 0;
1076 		bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
1077 		while (bpf_map_get_next_key(map_fd[i], &key, &next_key) == 0) {
1078 			bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
1079 			key = next_key;
1080 		}
1081 	}
1082 
1083 	close(s1);
1084 	close(s2);
1085 	close(p1);
1086 	close(p2);
1087 	close(c1);
1088 	close(c2);
1089 	return err;
1090 }
1091 
1092 static char *test_to_str(int test)
1093 {
1094 	switch (test) {
1095 	case SENDMSG:
1096 		return "sendmsg";
1097 	case SENDPAGE:
1098 		return "sendpage";
1099 	}
1100 	return "unknown";
1101 }
1102 
1103 #define OPTSTRING 60
1104 static void test_options(char *options)
1105 {
1106 	char tstr[OPTSTRING];
1107 
1108 	memset(options, 0, OPTSTRING);
1109 
1110 	if (txmsg_pass)
1111 		strncat(options, "pass,", OPTSTRING);
1112 	if (txmsg_noisy)
1113 		strncat(options, "pass_noisy,", OPTSTRING);
1114 	if (txmsg_redir)
1115 		strncat(options, "redir,", OPTSTRING);
1116 	if (txmsg_redir_noisy)
1117 		strncat(options, "redir_noisy,", OPTSTRING);
1118 	if (txmsg_drop)
1119 		strncat(options, "drop,", OPTSTRING);
1120 	if (txmsg_apply) {
1121 		snprintf(tstr, OPTSTRING, "apply %d,", txmsg_apply);
1122 		strncat(options, tstr, OPTSTRING);
1123 	}
1124 	if (txmsg_cork) {
1125 		snprintf(tstr, OPTSTRING, "cork %d,", txmsg_cork);
1126 		strncat(options, tstr, OPTSTRING);
1127 	}
1128 	if (txmsg_start) {
1129 		snprintf(tstr, OPTSTRING, "start %d,", txmsg_start);
1130 		strncat(options, tstr, OPTSTRING);
1131 	}
1132 	if (txmsg_end) {
1133 		snprintf(tstr, OPTSTRING, "end %d,", txmsg_end);
1134 		strncat(options, tstr, OPTSTRING);
1135 	}
1136 	if (txmsg_start_pop) {
1137 		snprintf(tstr, OPTSTRING, "pop (%d,%d),",
1138 			 txmsg_start_pop, txmsg_start_pop + txmsg_pop);
1139 		strncat(options, tstr, OPTSTRING);
1140 	}
1141 	if (txmsg_ingress)
1142 		strncat(options, "ingress,", OPTSTRING);
1143 	if (txmsg_skb)
1144 		strncat(options, "skb,", OPTSTRING);
1145 	if (ktls)
1146 		strncat(options, "ktls,", OPTSTRING);
1147 	if (peek_flag)
1148 		strncat(options, "peek,", OPTSTRING);
1149 }
1150 
1151 static int __test_exec(int cgrp, int test, struct sockmap_options *opt)
1152 {
1153 	char *options = calloc(OPTSTRING, sizeof(char));
1154 	int err;
1155 
1156 	if (test == SENDPAGE)
1157 		opt->sendpage = true;
1158 	else
1159 		opt->sendpage = false;
1160 
1161 	if (txmsg_drop)
1162 		opt->drop_expected = true;
1163 	else
1164 		opt->drop_expected = false;
1165 
1166 	test_options(options);
1167 
1168 	fprintf(stdout,
1169 		"[TEST %i]: (%i, %i, %i, %s, %s): ",
1170 		test_cnt, opt->rate, opt->iov_count, opt->iov_length,
1171 		test_to_str(test), options);
1172 	fflush(stdout);
1173 	err = run_options(opt, cgrp, test);
1174 	fprintf(stdout, "%s\n", !err ? "PASS" : "FAILED");
1175 	test_cnt++;
1176 	!err ? passed++ : failed++;
1177 	free(options);
1178 	return err;
1179 }
1180 
1181 static int test_exec(int cgrp, struct sockmap_options *opt)
1182 {
1183 	int err = __test_exec(cgrp, SENDMSG, opt);
1184 
1185 	if (err)
1186 		goto out;
1187 
1188 	err = __test_exec(cgrp, SENDPAGE, opt);
1189 out:
1190 	return err;
1191 }
1192 
1193 static int test_loop(int cgrp)
1194 {
1195 	struct sockmap_options opt;
1196 
1197 	int err, i, l, r;
1198 
1199 	opt.verbose = 0;
1200 	opt.base = false;
1201 	opt.sendpage = false;
1202 	opt.data_test = false;
1203 	opt.drop_expected = false;
1204 	opt.iov_count = 0;
1205 	opt.iov_length = 0;
1206 	opt.rate = 0;
1207 
1208 	r = 1;
1209 	for (i = 1; i < 100; i += 33) {
1210 		for (l = 1; l < 100; l += 33) {
1211 			opt.rate = r;
1212 			opt.iov_count = i;
1213 			opt.iov_length = l;
1214 			err = test_exec(cgrp, &opt);
1215 			if (err)
1216 				goto out;
1217 		}
1218 	}
1219 	sched_yield();
1220 out:
1221 	return err;
1222 }
1223 
1224 static int test_txmsg(int cgrp)
1225 {
1226 	int err;
1227 
1228 	txmsg_pass = txmsg_noisy = txmsg_redir_noisy = txmsg_drop = 0;
1229 	txmsg_apply = txmsg_cork = 0;
1230 	txmsg_ingress = txmsg_skb = 0;
1231 
1232 	txmsg_pass = 1;
1233 	err = test_loop(cgrp);
1234 	txmsg_pass = 0;
1235 	if (err)
1236 		goto out;
1237 
1238 	txmsg_redir = 1;
1239 	err = test_loop(cgrp);
1240 	txmsg_redir = 0;
1241 	if (err)
1242 		goto out;
1243 
1244 	txmsg_drop = 1;
1245 	err = test_loop(cgrp);
1246 	txmsg_drop = 0;
1247 	if (err)
1248 		goto out;
1249 
1250 	txmsg_redir = 1;
1251 	txmsg_ingress = 1;
1252 	err = test_loop(cgrp);
1253 	txmsg_redir = 0;
1254 	txmsg_ingress = 0;
1255 	if (err)
1256 		goto out;
1257 out:
1258 	txmsg_pass = 0;
1259 	txmsg_redir = 0;
1260 	txmsg_drop = 0;
1261 	return err;
1262 }
1263 
1264 static int test_send(struct sockmap_options *opt, int cgrp)
1265 {
1266 	int err;
1267 
1268 	opt->iov_length = 1;
1269 	opt->iov_count = 1;
1270 	opt->rate = 1;
1271 	err = test_exec(cgrp, opt);
1272 	if (err)
1273 		goto out;
1274 
1275 	opt->iov_length = 1;
1276 	opt->iov_count = 1024;
1277 	opt->rate = 1;
1278 	err = test_exec(cgrp, opt);
1279 	if (err)
1280 		goto out;
1281 
1282 	opt->iov_length = 1024;
1283 	opt->iov_count = 1;
1284 	opt->rate = 1;
1285 	err = test_exec(cgrp, opt);
1286 	if (err)
1287 		goto out;
1288 
1289 	opt->iov_length = 1;
1290 	opt->iov_count = 1;
1291 	opt->rate = 512;
1292 	err = test_exec(cgrp, opt);
1293 	if (err)
1294 		goto out;
1295 
1296 	opt->iov_length = 256;
1297 	opt->iov_count = 1024;
1298 	opt->rate = 2;
1299 	err = test_exec(cgrp, opt);
1300 	if (err)
1301 		goto out;
1302 
1303 	opt->rate = 100;
1304 	opt->iov_count = 1;
1305 	opt->iov_length = 5;
1306 	err = test_exec(cgrp, opt);
1307 	if (err)
1308 		goto out;
1309 out:
1310 	sched_yield();
1311 	return err;
1312 }
1313 
1314 static int test_mixed(int cgrp)
1315 {
1316 	struct sockmap_options opt = {0};
1317 	int err;
1318 
1319 	txmsg_pass = txmsg_noisy = txmsg_redir_noisy = txmsg_drop = 0;
1320 	txmsg_apply = txmsg_cork = 0;
1321 	txmsg_start = txmsg_end = 0;
1322 	txmsg_start_push = txmsg_end_push = 0;
1323 	txmsg_start_pop = txmsg_pop = 0;
1324 
1325 	/* Test small and large iov_count values with pass/redir/apply/cork */
1326 	txmsg_pass = 1;
1327 	txmsg_redir = 0;
1328 	txmsg_apply = 1;
1329 	txmsg_cork = 0;
1330 	err = test_send(&opt, cgrp);
1331 	if (err)
1332 		goto out;
1333 
1334 	txmsg_pass = 1;
1335 	txmsg_redir = 0;
1336 	txmsg_apply = 0;
1337 	txmsg_cork = 1;
1338 	err = test_send(&opt, cgrp);
1339 	if (err)
1340 		goto out;
1341 
1342 	txmsg_pass = 1;
1343 	txmsg_redir = 0;
1344 	txmsg_apply = 1;
1345 	txmsg_cork = 1;
1346 	err = test_send(&opt, cgrp);
1347 	if (err)
1348 		goto out;
1349 
1350 	txmsg_pass = 1;
1351 	txmsg_redir = 0;
1352 	txmsg_apply = 1024;
1353 	txmsg_cork = 0;
1354 	err = test_send(&opt, cgrp);
1355 	if (err)
1356 		goto out;
1357 
1358 	txmsg_pass = 1;
1359 	txmsg_redir = 0;
1360 	txmsg_apply = 0;
1361 	txmsg_cork = 1024;
1362 	err = test_send(&opt, cgrp);
1363 	if (err)
1364 		goto out;
1365 
1366 	txmsg_pass = 1;
1367 	txmsg_redir = 0;
1368 	txmsg_apply = 1024;
1369 	txmsg_cork = 1024;
1370 	err = test_send(&opt, cgrp);
1371 	if (err)
1372 		goto out;
1373 
1374 	txmsg_pass = 1;
1375 	txmsg_redir = 0;
1376 	txmsg_cork = 4096;
1377 	txmsg_apply = 4096;
1378 	err = test_send(&opt, cgrp);
1379 	if (err)
1380 		goto out;
1381 
1382 	txmsg_pass = 0;
1383 	txmsg_redir = 1;
1384 	txmsg_apply = 1;
1385 	txmsg_cork = 0;
1386 	err = test_send(&opt, cgrp);
1387 	if (err)
1388 		goto out;
1389 
1390 	txmsg_pass = 0;
1391 	txmsg_redir = 1;
1392 	txmsg_apply = 0;
1393 	txmsg_cork = 1;
1394 	err = test_send(&opt, cgrp);
1395 	if (err)
1396 		goto out;
1397 
1398 	txmsg_pass = 0;
1399 	txmsg_redir = 1;
1400 	txmsg_apply = 1024;
1401 	txmsg_cork = 0;
1402 	err = test_send(&opt, cgrp);
1403 	if (err)
1404 		goto out;
1405 
1406 	txmsg_pass = 0;
1407 	txmsg_redir = 1;
1408 	txmsg_apply = 0;
1409 	txmsg_cork = 1024;
1410 	err = test_send(&opt, cgrp);
1411 	if (err)
1412 		goto out;
1413 
1414 	txmsg_pass = 0;
1415 	txmsg_redir = 1;
1416 	txmsg_apply = 1024;
1417 	txmsg_cork = 1024;
1418 	err = test_send(&opt, cgrp);
1419 	if (err)
1420 		goto out;
1421 
1422 	txmsg_pass = 0;
1423 	txmsg_redir = 1;
1424 	txmsg_cork = 4096;
1425 	txmsg_apply = 4096;
1426 	err = test_send(&opt, cgrp);
1427 	if (err)
1428 		goto out;
1429 out:
1430 	return err;
1431 }
1432 
1433 static int test_start_end(int cgrp)
1434 {
1435 	struct sockmap_options opt = {0};
1436 	int err, i;
1437 
1438 	/* Test basic start/end with lots of iov_count and iov_lengths */
1439 	txmsg_start = 1;
1440 	txmsg_end = 2;
1441 	txmsg_start_push = 1;
1442 	txmsg_end_push = 2;
1443 	txmsg_start_pop = 1;
1444 	txmsg_pop = 1;
1445 	err = test_txmsg(cgrp);
1446 	if (err)
1447 		goto out;
1448 
1449 	/* Cut a byte of pushed data but leave reamining in place */
1450 	txmsg_start = 1;
1451 	txmsg_end = 2;
1452 	txmsg_start_push = 1;
1453 	txmsg_end_push = 3;
1454 	txmsg_start_pop = 1;
1455 	txmsg_pop = 1;
1456 	err = test_txmsg(cgrp);
1457 	if (err)
1458 		goto out;
1459 
1460 	/* Test start/end with cork */
1461 	opt.rate = 16;
1462 	opt.iov_count = 1;
1463 	opt.iov_length = 100;
1464 	txmsg_cork = 1600;
1465 
1466 	txmsg_start_pop = 0;
1467 	txmsg_pop = 0;
1468 
1469 	for (i = 99; i <= 1600; i += 500) {
1470 		txmsg_start = 0;
1471 		txmsg_end = i;
1472 		txmsg_start_push = 0;
1473 		txmsg_end_push = i;
1474 		err = test_exec(cgrp, &opt);
1475 		if (err)
1476 			goto out;
1477 	}
1478 
1479 	/* Test pop data in middle of cork */
1480 	for (i = 99; i <= 1600; i += 500) {
1481 		txmsg_start_pop = 10;
1482 		txmsg_pop = i;
1483 		err = test_exec(cgrp, &opt);
1484 		if (err)
1485 			goto out;
1486 	}
1487 	txmsg_start_pop = 0;
1488 	txmsg_pop = 0;
1489 
1490 	/* Test start/end with cork but pull data in middle */
1491 	for (i = 199; i <= 1600; i += 500) {
1492 		txmsg_start = 100;
1493 		txmsg_end = i;
1494 		txmsg_start_push = 100;
1495 		txmsg_end_push = i;
1496 		err = test_exec(cgrp, &opt);
1497 		if (err)
1498 			goto out;
1499 	}
1500 
1501 	/* Test start/end with cork pulling last sg entry */
1502 	txmsg_start = 1500;
1503 	txmsg_end = 1600;
1504 	txmsg_start_push = 1500;
1505 	txmsg_end_push = 1600;
1506 	err = test_exec(cgrp, &opt);
1507 	if (err)
1508 		goto out;
1509 
1510 	/* Test pop with cork pulling last sg entry */
1511 	txmsg_start_pop = 1500;
1512 	txmsg_pop = 1600;
1513 	err = test_exec(cgrp, &opt);
1514 	if (err)
1515 		goto out;
1516 	txmsg_start_pop = 0;
1517 	txmsg_pop = 0;
1518 
1519 	/* Test start/end pull of single byte in last page */
1520 	txmsg_start = 1111;
1521 	txmsg_end = 1112;
1522 	txmsg_start_push = 1111;
1523 	txmsg_end_push = 1112;
1524 	err = test_exec(cgrp, &opt);
1525 	if (err)
1526 		goto out;
1527 
1528 	/* Test pop of single byte in last page */
1529 	txmsg_start_pop = 1111;
1530 	txmsg_pop = 1112;
1531 	err = test_exec(cgrp, &opt);
1532 	if (err)
1533 		goto out;
1534 
1535 	/* Test start/end with end < start */
1536 	txmsg_start = 1111;
1537 	txmsg_end = 0;
1538 	txmsg_start_push = 1111;
1539 	txmsg_end_push = 0;
1540 	err = test_exec(cgrp, &opt);
1541 	if (err)
1542 		goto out;
1543 
1544 	/* Test start/end with end > data */
1545 	txmsg_start = 0;
1546 	txmsg_end = 1601;
1547 	txmsg_start_push = 0;
1548 	txmsg_end_push = 1601;
1549 	err = test_exec(cgrp, &opt);
1550 	if (err)
1551 		goto out;
1552 
1553 	/* Test start/end with start > data */
1554 	txmsg_start = 1601;
1555 	txmsg_end = 1600;
1556 	txmsg_start_push = 1601;
1557 	txmsg_end_push = 1600;
1558 	err = test_exec(cgrp, &opt);
1559 	if (err)
1560 		goto out;
1561 
1562 	/* Test pop with start > data */
1563 	txmsg_start_pop = 1601;
1564 	txmsg_pop = 1;
1565 	err = test_exec(cgrp, &opt);
1566 	if (err)
1567 		goto out;
1568 
1569 	/* Test pop with pop range > data */
1570 	txmsg_start_pop = 1599;
1571 	txmsg_pop = 10;
1572 	err = test_exec(cgrp, &opt);
1573 out:
1574 	txmsg_start = 0;
1575 	txmsg_end = 0;
1576 	sched_yield();
1577 	return err;
1578 }
1579 
1580 char *map_names[] = {
1581 	"sock_map",
1582 	"sock_map_txmsg",
1583 	"sock_map_redir",
1584 	"sock_apply_bytes",
1585 	"sock_cork_bytes",
1586 	"sock_bytes",
1587 	"sock_redir_flags",
1588 	"sock_skb_opts",
1589 };
1590 
1591 int prog_attach_type[] = {
1592 	BPF_SK_SKB_STREAM_PARSER,
1593 	BPF_SK_SKB_STREAM_VERDICT,
1594 	BPF_CGROUP_SOCK_OPS,
1595 	BPF_SK_MSG_VERDICT,
1596 	BPF_SK_MSG_VERDICT,
1597 	BPF_SK_MSG_VERDICT,
1598 	BPF_SK_MSG_VERDICT,
1599 	BPF_SK_MSG_VERDICT,
1600 	BPF_SK_MSG_VERDICT,
1601 	BPF_SK_MSG_VERDICT,
1602 };
1603 
1604 int prog_type[] = {
1605 	BPF_PROG_TYPE_SK_SKB,
1606 	BPF_PROG_TYPE_SK_SKB,
1607 	BPF_PROG_TYPE_SOCK_OPS,
1608 	BPF_PROG_TYPE_SK_MSG,
1609 	BPF_PROG_TYPE_SK_MSG,
1610 	BPF_PROG_TYPE_SK_MSG,
1611 	BPF_PROG_TYPE_SK_MSG,
1612 	BPF_PROG_TYPE_SK_MSG,
1613 	BPF_PROG_TYPE_SK_MSG,
1614 	BPF_PROG_TYPE_SK_MSG,
1615 };
1616 
1617 static int populate_progs(char *bpf_file)
1618 {
1619 	struct bpf_program *prog;
1620 	struct bpf_object *obj;
1621 	int i = 0;
1622 	long err;
1623 
1624 	obj = bpf_object__open(bpf_file);
1625 	err = libbpf_get_error(obj);
1626 	if (err) {
1627 		char err_buf[256];
1628 
1629 		libbpf_strerror(err, err_buf, sizeof(err_buf));
1630 		printf("Unable to load eBPF objects in file '%s' : %s\n",
1631 		       bpf_file, err_buf);
1632 		return -1;
1633 	}
1634 
1635 	bpf_object__for_each_program(prog, obj) {
1636 		bpf_program__set_type(prog, prog_type[i]);
1637 		bpf_program__set_expected_attach_type(prog,
1638 						      prog_attach_type[i]);
1639 		i++;
1640 	}
1641 
1642 	i = bpf_object__load(obj);
1643 	i = 0;
1644 	bpf_object__for_each_program(prog, obj) {
1645 		prog_fd[i] = bpf_program__fd(prog);
1646 		i++;
1647 	}
1648 
1649 	for (i = 0; i < sizeof(map_fd)/sizeof(int); i++) {
1650 		maps[i] = bpf_object__find_map_by_name(obj, map_names[i]);
1651 		map_fd[i] = bpf_map__fd(maps[i]);
1652 		if (map_fd[i] < 0) {
1653 			fprintf(stderr, "load_bpf_file: (%i) %s\n",
1654 				map_fd[i], strerror(errno));
1655 			return -1;
1656 		}
1657 	}
1658 
1659 	return 0;
1660 }
1661 
1662 static int __test_suite(int cg_fd, char *bpf_file)
1663 {
1664 	int err, cleanup = cg_fd;
1665 
1666 	err = populate_progs(bpf_file);
1667 	if (err < 0) {
1668 		fprintf(stderr, "ERROR: (%i) load bpf failed\n", err);
1669 		return err;
1670 	}
1671 
1672 	if (cg_fd < 0) {
1673 		if (setup_cgroup_environment()) {
1674 			fprintf(stderr, "ERROR: cgroup env failed\n");
1675 			return -EINVAL;
1676 		}
1677 
1678 		cg_fd = create_and_get_cgroup(CG_PATH);
1679 		if (cg_fd < 0) {
1680 			fprintf(stderr,
1681 				"ERROR: (%i) open cg path failed: %s\n",
1682 				cg_fd, optarg);
1683 			return cg_fd;
1684 		}
1685 
1686 		if (join_cgroup(CG_PATH)) {
1687 			fprintf(stderr, "ERROR: failed to join cgroup\n");
1688 			return -EINVAL;
1689 		}
1690 	}
1691 
1692 	/* Tests basic commands and APIs with range of iov values */
1693 	txmsg_start = txmsg_end = txmsg_start_push = txmsg_end_push = 0;
1694 	err = test_txmsg(cg_fd);
1695 	if (err)
1696 		goto out;
1697 
1698 	/* Tests interesting combinations of APIs used together */
1699 	err = test_mixed(cg_fd);
1700 	if (err)
1701 		goto out;
1702 
1703 	/* Tests pull_data API using start/end API */
1704 	err = test_start_end(cg_fd);
1705 	if (err)
1706 		goto out;
1707 
1708 out:
1709 	printf("Summary: %i PASSED %i FAILED\n", passed, failed);
1710 	if (cleanup < 0) {
1711 		cleanup_cgroup_environment();
1712 		close(cg_fd);
1713 	}
1714 	return err;
1715 }
1716 
1717 static int test_suite(int cg_fd)
1718 {
1719 	int err;
1720 
1721 	err = __test_suite(cg_fd, BPF_SOCKMAP_FILENAME);
1722 	if (err)
1723 		goto out;
1724 	err = __test_suite(cg_fd, BPF_SOCKHASH_FILENAME);
1725 out:
1726 	if (cg_fd > -1)
1727 		close(cg_fd);
1728 	return err;
1729 }
1730 
1731 int main(int argc, char **argv)
1732 {
1733 	int iov_count = 1, length = 1024, rate = 1;
1734 	struct sockmap_options options = {0};
1735 	int opt, longindex, err, cg_fd = 0;
1736 	char *bpf_file = BPF_SOCKMAP_FILENAME;
1737 	int test = PING_PONG;
1738 
1739 	if (argc < 2)
1740 		return test_suite(-1);
1741 
1742 	while ((opt = getopt_long(argc, argv, ":dhvc:r:i:l:t:p:q:",
1743 				  long_options, &longindex)) != -1) {
1744 		switch (opt) {
1745 		case 's':
1746 			txmsg_start = atoi(optarg);
1747 			break;
1748 		case 'e':
1749 			txmsg_end = atoi(optarg);
1750 			break;
1751 		case 'p':
1752 			txmsg_start_push = atoi(optarg);
1753 			break;
1754 		case 'q':
1755 			txmsg_end_push = atoi(optarg);
1756 			break;
1757 		case 'w':
1758 			txmsg_start_pop = atoi(optarg);
1759 			break;
1760 		case 'x':
1761 			txmsg_pop = atoi(optarg);
1762 			break;
1763 		case 'a':
1764 			txmsg_apply = atoi(optarg);
1765 			break;
1766 		case 'k':
1767 			txmsg_cork = atoi(optarg);
1768 			break;
1769 		case 'c':
1770 			cg_fd = open(optarg, O_DIRECTORY, O_RDONLY);
1771 			if (cg_fd < 0) {
1772 				fprintf(stderr,
1773 					"ERROR: (%i) open cg path failed: %s\n",
1774 					cg_fd, optarg);
1775 				return cg_fd;
1776 			}
1777 			break;
1778 		case 'r':
1779 			rate = atoi(optarg);
1780 			break;
1781 		case 'v':
1782 			options.verbose = 1;
1783 			break;
1784 		case 'i':
1785 			iov_count = atoi(optarg);
1786 			break;
1787 		case 'l':
1788 			length = atoi(optarg);
1789 			break;
1790 		case 'd':
1791 			options.data_test = true;
1792 			break;
1793 		case 't':
1794 			if (strcmp(optarg, "ping") == 0) {
1795 				test = PING_PONG;
1796 			} else if (strcmp(optarg, "sendmsg") == 0) {
1797 				test = SENDMSG;
1798 			} else if (strcmp(optarg, "base") == 0) {
1799 				test = BASE;
1800 			} else if (strcmp(optarg, "base_sendpage") == 0) {
1801 				test = BASE_SENDPAGE;
1802 			} else if (strcmp(optarg, "sendpage") == 0) {
1803 				test = SENDPAGE;
1804 			} else {
1805 				usage(argv);
1806 				return -1;
1807 			}
1808 			break;
1809 		case 0:
1810 			break;
1811 		case 'h':
1812 		default:
1813 			usage(argv);
1814 			return -1;
1815 		}
1816 	}
1817 
1818 	if (argc <= 3 && cg_fd)
1819 		return test_suite(cg_fd);
1820 
1821 	if (!cg_fd) {
1822 		fprintf(stderr, "%s requires cgroup option: --cgroup <path>\n",
1823 			argv[0]);
1824 		return -1;
1825 	}
1826 
1827 	err = populate_progs(bpf_file);
1828 	if (err) {
1829 		fprintf(stderr, "populate program: (%s) %s\n",
1830 			bpf_file, strerror(errno));
1831 		return 1;
1832 	}
1833 	running = 1;
1834 
1835 	/* catch SIGINT */
1836 	signal(SIGINT, running_handler);
1837 
1838 	options.iov_count = iov_count;
1839 	options.iov_length = length;
1840 	options.rate = rate;
1841 
1842 	err = run_options(&options, cg_fd, test);
1843 	close(cg_fd);
1844 	return err;
1845 }
1846 
1847 void running_handler(int a)
1848 {
1849 	running = 0;
1850 }
1851