Linux Audio

Check our new training course

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