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