Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

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