18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci// Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io
38c2ecf20Sopenharmony_ci#include <stdio.h>
48c2ecf20Sopenharmony_ci#include <stdlib.h>
58c2ecf20Sopenharmony_ci#include <sys/socket.h>
68c2ecf20Sopenharmony_ci#include <sys/ioctl.h>
78c2ecf20Sopenharmony_ci#include <sys/select.h>
88c2ecf20Sopenharmony_ci#include <netinet/in.h>
98c2ecf20Sopenharmony_ci#include <arpa/inet.h>
108c2ecf20Sopenharmony_ci#include <unistd.h>
118c2ecf20Sopenharmony_ci#include <string.h>
128c2ecf20Sopenharmony_ci#include <errno.h>
138c2ecf20Sopenharmony_ci#include <stdbool.h>
148c2ecf20Sopenharmony_ci#include <signal.h>
158c2ecf20Sopenharmony_ci#include <fcntl.h>
168c2ecf20Sopenharmony_ci#include <sys/wait.h>
178c2ecf20Sopenharmony_ci#include <time.h>
188c2ecf20Sopenharmony_ci#include <sched.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <sys/time.h>
218c2ecf20Sopenharmony_ci#include <sys/resource.h>
228c2ecf20Sopenharmony_ci#include <sys/types.h>
238c2ecf20Sopenharmony_ci#include <sys/sendfile.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include <linux/netlink.h>
268c2ecf20Sopenharmony_ci#include <linux/socket.h>
278c2ecf20Sopenharmony_ci#include <linux/sock_diag.h>
288c2ecf20Sopenharmony_ci#include <linux/bpf.h>
298c2ecf20Sopenharmony_ci#include <linux/if_link.h>
308c2ecf20Sopenharmony_ci#include <linux/tls.h>
318c2ecf20Sopenharmony_ci#include <assert.h>
328c2ecf20Sopenharmony_ci#include <libgen.h>
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include <getopt.h>
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <bpf/bpf.h>
378c2ecf20Sopenharmony_ci#include <bpf/libbpf.h>
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#include "bpf_util.h"
408c2ecf20Sopenharmony_ci#include "bpf_rlimit.h"
418c2ecf20Sopenharmony_ci#include "cgroup_helpers.h"
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ciint running;
448c2ecf20Sopenharmony_cistatic void running_handler(int a);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#ifndef TCP_ULP
478c2ecf20Sopenharmony_ci# define TCP_ULP 31
488c2ecf20Sopenharmony_ci#endif
498c2ecf20Sopenharmony_ci#ifndef SOL_TLS
508c2ecf20Sopenharmony_ci# define SOL_TLS 282
518c2ecf20Sopenharmony_ci#endif
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/* randomly selected ports for testing on lo */
548c2ecf20Sopenharmony_ci#define S1_PORT 10000
558c2ecf20Sopenharmony_ci#define S2_PORT 10001
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define BPF_SOCKMAP_FILENAME  "test_sockmap_kern.o"
588c2ecf20Sopenharmony_ci#define BPF_SOCKHASH_FILENAME "test_sockhash_kern.o"
598c2ecf20Sopenharmony_ci#define CG_PATH "/sockmap"
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/* global sockets */
628c2ecf20Sopenharmony_ciint s1, s2, c1, c2, p1, p2;
638c2ecf20Sopenharmony_ciint test_cnt;
648c2ecf20Sopenharmony_ciint passed;
658c2ecf20Sopenharmony_ciint failed;
668c2ecf20Sopenharmony_ciint map_fd[9];
678c2ecf20Sopenharmony_cistruct bpf_map *maps[9];
688c2ecf20Sopenharmony_ciint prog_fd[11];
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ciint txmsg_pass;
718c2ecf20Sopenharmony_ciint txmsg_redir;
728c2ecf20Sopenharmony_ciint txmsg_drop;
738c2ecf20Sopenharmony_ciint txmsg_apply;
748c2ecf20Sopenharmony_ciint txmsg_cork;
758c2ecf20Sopenharmony_ciint txmsg_start;
768c2ecf20Sopenharmony_ciint txmsg_end;
778c2ecf20Sopenharmony_ciint txmsg_start_push;
788c2ecf20Sopenharmony_ciint txmsg_end_push;
798c2ecf20Sopenharmony_ciint txmsg_start_pop;
808c2ecf20Sopenharmony_ciint txmsg_pop;
818c2ecf20Sopenharmony_ciint txmsg_ingress;
828c2ecf20Sopenharmony_ciint txmsg_redir_skb;
838c2ecf20Sopenharmony_ciint txmsg_ktls_skb;
848c2ecf20Sopenharmony_ciint txmsg_ktls_skb_drop;
858c2ecf20Sopenharmony_ciint txmsg_ktls_skb_redir;
868c2ecf20Sopenharmony_ciint ktls;
878c2ecf20Sopenharmony_ciint peek_flag;
888c2ecf20Sopenharmony_ciint skb_use_parser;
898c2ecf20Sopenharmony_ciint txmsg_omit_skb_parser;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic const struct option long_options[] = {
928c2ecf20Sopenharmony_ci	{"help",	no_argument,		NULL, 'h' },
938c2ecf20Sopenharmony_ci	{"cgroup",	required_argument,	NULL, 'c' },
948c2ecf20Sopenharmony_ci	{"rate",	required_argument,	NULL, 'r' },
958c2ecf20Sopenharmony_ci	{"verbose",	optional_argument,	NULL, 'v' },
968c2ecf20Sopenharmony_ci	{"iov_count",	required_argument,	NULL, 'i' },
978c2ecf20Sopenharmony_ci	{"length",	required_argument,	NULL, 'l' },
988c2ecf20Sopenharmony_ci	{"test",	required_argument,	NULL, 't' },
998c2ecf20Sopenharmony_ci	{"data_test",   no_argument,		NULL, 'd' },
1008c2ecf20Sopenharmony_ci	{"txmsg",		no_argument,	&txmsg_pass,  1  },
1018c2ecf20Sopenharmony_ci	{"txmsg_redir",		no_argument,	&txmsg_redir, 1  },
1028c2ecf20Sopenharmony_ci	{"txmsg_drop",		no_argument,	&txmsg_drop, 1 },
1038c2ecf20Sopenharmony_ci	{"txmsg_apply",	required_argument,	NULL, 'a'},
1048c2ecf20Sopenharmony_ci	{"txmsg_cork",	required_argument,	NULL, 'k'},
1058c2ecf20Sopenharmony_ci	{"txmsg_start", required_argument,	NULL, 's'},
1068c2ecf20Sopenharmony_ci	{"txmsg_end",	required_argument,	NULL, 'e'},
1078c2ecf20Sopenharmony_ci	{"txmsg_start_push", required_argument,	NULL, 'p'},
1088c2ecf20Sopenharmony_ci	{"txmsg_end_push",   required_argument,	NULL, 'q'},
1098c2ecf20Sopenharmony_ci	{"txmsg_start_pop",  required_argument,	NULL, 'w'},
1108c2ecf20Sopenharmony_ci	{"txmsg_pop",	     required_argument,	NULL, 'x'},
1118c2ecf20Sopenharmony_ci	{"txmsg_ingress", no_argument,		&txmsg_ingress, 1 },
1128c2ecf20Sopenharmony_ci	{"txmsg_redir_skb", no_argument,	&txmsg_redir_skb, 1 },
1138c2ecf20Sopenharmony_ci	{"ktls", no_argument,			&ktls, 1 },
1148c2ecf20Sopenharmony_ci	{"peek", no_argument,			&peek_flag, 1 },
1158c2ecf20Sopenharmony_ci	{"txmsg_omit_skb_parser", no_argument,      &txmsg_omit_skb_parser, 1},
1168c2ecf20Sopenharmony_ci	{"whitelist", required_argument,	NULL, 'n' },
1178c2ecf20Sopenharmony_ci	{"blacklist", required_argument,	NULL, 'b' },
1188c2ecf20Sopenharmony_ci	{0, 0, NULL, 0 }
1198c2ecf20Sopenharmony_ci};
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistruct test_env {
1228c2ecf20Sopenharmony_ci	const char *type;
1238c2ecf20Sopenharmony_ci	const char *subtest;
1248c2ecf20Sopenharmony_ci	const char *prepend;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	int test_num;
1278c2ecf20Sopenharmony_ci	int subtest_num;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	int succ_cnt;
1308c2ecf20Sopenharmony_ci	int fail_cnt;
1318c2ecf20Sopenharmony_ci	int fail_last;
1328c2ecf20Sopenharmony_ci};
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistruct test_env env;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistruct sockmap_options {
1378c2ecf20Sopenharmony_ci	int verbose;
1388c2ecf20Sopenharmony_ci	bool base;
1398c2ecf20Sopenharmony_ci	bool sendpage;
1408c2ecf20Sopenharmony_ci	bool data_test;
1418c2ecf20Sopenharmony_ci	bool drop_expected;
1428c2ecf20Sopenharmony_ci	int iov_count;
1438c2ecf20Sopenharmony_ci	int iov_length;
1448c2ecf20Sopenharmony_ci	int rate;
1458c2ecf20Sopenharmony_ci	char *map;
1468c2ecf20Sopenharmony_ci	char *whitelist;
1478c2ecf20Sopenharmony_ci	char *blacklist;
1488c2ecf20Sopenharmony_ci	char *prepend;
1498c2ecf20Sopenharmony_ci};
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistruct _test {
1528c2ecf20Sopenharmony_ci	char *title;
1538c2ecf20Sopenharmony_ci	void (*tester)(int cg_fd, struct sockmap_options *opt);
1548c2ecf20Sopenharmony_ci};
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistatic void test_start(void)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	env.subtest_num++;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void test_fail(void)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	env.fail_cnt++;
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic void test_pass(void)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	env.succ_cnt++;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_cistatic void test_reset(void)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	txmsg_start = txmsg_end = 0;
1748c2ecf20Sopenharmony_ci	txmsg_start_pop = txmsg_pop = 0;
1758c2ecf20Sopenharmony_ci	txmsg_start_push = txmsg_end_push = 0;
1768c2ecf20Sopenharmony_ci	txmsg_pass = txmsg_drop = txmsg_redir = 0;
1778c2ecf20Sopenharmony_ci	txmsg_apply = txmsg_cork = 0;
1788c2ecf20Sopenharmony_ci	txmsg_ingress = txmsg_redir_skb = 0;
1798c2ecf20Sopenharmony_ci	txmsg_ktls_skb = txmsg_ktls_skb_drop = txmsg_ktls_skb_redir = 0;
1808c2ecf20Sopenharmony_ci	txmsg_omit_skb_parser = 0;
1818c2ecf20Sopenharmony_ci	skb_use_parser = 0;
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_cistatic int test_start_subtest(const struct _test *t, struct sockmap_options *o)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	env.type = o->map;
1878c2ecf20Sopenharmony_ci	env.subtest = t->title;
1888c2ecf20Sopenharmony_ci	env.prepend = o->prepend;
1898c2ecf20Sopenharmony_ci	env.test_num++;
1908c2ecf20Sopenharmony_ci	env.subtest_num = 0;
1918c2ecf20Sopenharmony_ci	env.fail_last = env.fail_cnt;
1928c2ecf20Sopenharmony_ci	test_reset();
1938c2ecf20Sopenharmony_ci	return 0;
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic void test_end_subtest(void)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	int error = env.fail_cnt - env.fail_last;
1998c2ecf20Sopenharmony_ci	int type = strcmp(env.type, BPF_SOCKMAP_FILENAME);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	if (!error)
2028c2ecf20Sopenharmony_ci		test_pass();
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	fprintf(stdout, "#%2d/%2d %8s:%s:%s:%s\n",
2058c2ecf20Sopenharmony_ci		env.test_num, env.subtest_num,
2068c2ecf20Sopenharmony_ci		!type ? "sockmap" : "sockhash",
2078c2ecf20Sopenharmony_ci		env.prepend ? : "",
2088c2ecf20Sopenharmony_ci		env.subtest, error ? "FAIL" : "OK");
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic void test_print_results(void)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	fprintf(stdout, "Pass: %d Fail: %d\n",
2148c2ecf20Sopenharmony_ci		env.succ_cnt, env.fail_cnt);
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic void usage(char *argv[])
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	int i;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	printf(" Usage: %s --cgroup <cgroup_path>\n", argv[0]);
2228c2ecf20Sopenharmony_ci	printf(" options:\n");
2238c2ecf20Sopenharmony_ci	for (i = 0; long_options[i].name != 0; i++) {
2248c2ecf20Sopenharmony_ci		printf(" --%-12s", long_options[i].name);
2258c2ecf20Sopenharmony_ci		if (long_options[i].flag != NULL)
2268c2ecf20Sopenharmony_ci			printf(" flag (internal value:%d)\n",
2278c2ecf20Sopenharmony_ci				*long_options[i].flag);
2288c2ecf20Sopenharmony_ci		else
2298c2ecf20Sopenharmony_ci			printf(" -%c\n", long_options[i].val);
2308c2ecf20Sopenharmony_ci	}
2318c2ecf20Sopenharmony_ci	printf("\n");
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cichar *sock_to_string(int s)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	if (s == c1)
2378c2ecf20Sopenharmony_ci		return "client1";
2388c2ecf20Sopenharmony_ci	else if (s == c2)
2398c2ecf20Sopenharmony_ci		return "client2";
2408c2ecf20Sopenharmony_ci	else if (s == s1)
2418c2ecf20Sopenharmony_ci		return "server1";
2428c2ecf20Sopenharmony_ci	else if (s == s2)
2438c2ecf20Sopenharmony_ci		return "server2";
2448c2ecf20Sopenharmony_ci	else if (s == p1)
2458c2ecf20Sopenharmony_ci		return "peer1";
2468c2ecf20Sopenharmony_ci	else if (s == p2)
2478c2ecf20Sopenharmony_ci		return "peer2";
2488c2ecf20Sopenharmony_ci	else
2498c2ecf20Sopenharmony_ci		return "unknown";
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic int sockmap_init_ktls(int verbose, int s)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	struct tls12_crypto_info_aes_gcm_128 tls_tx = {
2558c2ecf20Sopenharmony_ci		.info = {
2568c2ecf20Sopenharmony_ci			.version     = TLS_1_2_VERSION,
2578c2ecf20Sopenharmony_ci			.cipher_type = TLS_CIPHER_AES_GCM_128,
2588c2ecf20Sopenharmony_ci		},
2598c2ecf20Sopenharmony_ci	};
2608c2ecf20Sopenharmony_ci	struct tls12_crypto_info_aes_gcm_128 tls_rx = {
2618c2ecf20Sopenharmony_ci		.info = {
2628c2ecf20Sopenharmony_ci			.version     = TLS_1_2_VERSION,
2638c2ecf20Sopenharmony_ci			.cipher_type = TLS_CIPHER_AES_GCM_128,
2648c2ecf20Sopenharmony_ci		},
2658c2ecf20Sopenharmony_ci	};
2668c2ecf20Sopenharmony_ci	int so_buf = 6553500;
2678c2ecf20Sopenharmony_ci	int err;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	err = setsockopt(s, 6, TCP_ULP, "tls", sizeof("tls"));
2708c2ecf20Sopenharmony_ci	if (err) {
2718c2ecf20Sopenharmony_ci		fprintf(stderr, "setsockopt: TCP_ULP(%s) failed with error %i\n", sock_to_string(s), err);
2728c2ecf20Sopenharmony_ci		return -EINVAL;
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci	err = setsockopt(s, SOL_TLS, TLS_TX, (void *)&tls_tx, sizeof(tls_tx));
2758c2ecf20Sopenharmony_ci	if (err) {
2768c2ecf20Sopenharmony_ci		fprintf(stderr, "setsockopt: TLS_TX(%s) failed with error %i\n", sock_to_string(s), err);
2778c2ecf20Sopenharmony_ci		return -EINVAL;
2788c2ecf20Sopenharmony_ci	}
2798c2ecf20Sopenharmony_ci	err = setsockopt(s, SOL_TLS, TLS_RX, (void *)&tls_rx, sizeof(tls_rx));
2808c2ecf20Sopenharmony_ci	if (err) {
2818c2ecf20Sopenharmony_ci		fprintf(stderr, "setsockopt: TLS_RX(%s) failed with error %i\n", sock_to_string(s), err);
2828c2ecf20Sopenharmony_ci		return -EINVAL;
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci	err = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &so_buf, sizeof(so_buf));
2858c2ecf20Sopenharmony_ci	if (err) {
2868c2ecf20Sopenharmony_ci		fprintf(stderr, "setsockopt: (%s) failed sndbuf with error %i\n", sock_to_string(s), err);
2878c2ecf20Sopenharmony_ci		return -EINVAL;
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci	err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &so_buf, sizeof(so_buf));
2908c2ecf20Sopenharmony_ci	if (err) {
2918c2ecf20Sopenharmony_ci		fprintf(stderr, "setsockopt: (%s) failed rcvbuf with error %i\n", sock_to_string(s), err);
2928c2ecf20Sopenharmony_ci		return -EINVAL;
2938c2ecf20Sopenharmony_ci	}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	if (verbose)
2968c2ecf20Sopenharmony_ci		fprintf(stdout, "socket(%s) kTLS enabled\n", sock_to_string(s));
2978c2ecf20Sopenharmony_ci	return 0;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_cistatic int sockmap_init_sockets(int verbose)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	int i, err, one = 1;
3028c2ecf20Sopenharmony_ci	struct sockaddr_in addr;
3038c2ecf20Sopenharmony_ci	int *fds[4] = {&s1, &s2, &c1, &c2};
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	s1 = s2 = p1 = p2 = c1 = c2 = 0;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	/* Init sockets */
3088c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
3098c2ecf20Sopenharmony_ci		*fds[i] = socket(AF_INET, SOCK_STREAM, 0);
3108c2ecf20Sopenharmony_ci		if (*fds[i] < 0) {
3118c2ecf20Sopenharmony_ci			perror("socket s1 failed()");
3128c2ecf20Sopenharmony_ci			return errno;
3138c2ecf20Sopenharmony_ci		}
3148c2ecf20Sopenharmony_ci	}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	/* Allow reuse */
3178c2ecf20Sopenharmony_ci	for (i = 0; i < 2; i++) {
3188c2ecf20Sopenharmony_ci		err = setsockopt(*fds[i], SOL_SOCKET, SO_REUSEADDR,
3198c2ecf20Sopenharmony_ci				 (char *)&one, sizeof(one));
3208c2ecf20Sopenharmony_ci		if (err) {
3218c2ecf20Sopenharmony_ci			perror("setsockopt failed()");
3228c2ecf20Sopenharmony_ci			return errno;
3238c2ecf20Sopenharmony_ci		}
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/* Non-blocking sockets */
3278c2ecf20Sopenharmony_ci	for (i = 0; i < 2; i++) {
3288c2ecf20Sopenharmony_ci		err = ioctl(*fds[i], FIONBIO, (char *)&one);
3298c2ecf20Sopenharmony_ci		if (err < 0) {
3308c2ecf20Sopenharmony_ci			perror("ioctl s1 failed()");
3318c2ecf20Sopenharmony_ci			return errno;
3328c2ecf20Sopenharmony_ci		}
3338c2ecf20Sopenharmony_ci	}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	/* Bind server sockets */
3368c2ecf20Sopenharmony_ci	memset(&addr, 0, sizeof(struct sockaddr_in));
3378c2ecf20Sopenharmony_ci	addr.sin_family = AF_INET;
3388c2ecf20Sopenharmony_ci	addr.sin_addr.s_addr = inet_addr("127.0.0.1");
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	addr.sin_port = htons(S1_PORT);
3418c2ecf20Sopenharmony_ci	err = bind(s1, (struct sockaddr *)&addr, sizeof(addr));
3428c2ecf20Sopenharmony_ci	if (err < 0) {
3438c2ecf20Sopenharmony_ci		perror("bind s1 failed()");
3448c2ecf20Sopenharmony_ci		return errno;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	addr.sin_port = htons(S2_PORT);
3488c2ecf20Sopenharmony_ci	err = bind(s2, (struct sockaddr *)&addr, sizeof(addr));
3498c2ecf20Sopenharmony_ci	if (err < 0) {
3508c2ecf20Sopenharmony_ci		perror("bind s2 failed()");
3518c2ecf20Sopenharmony_ci		return errno;
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	/* Listen server sockets */
3558c2ecf20Sopenharmony_ci	addr.sin_port = htons(S1_PORT);
3568c2ecf20Sopenharmony_ci	err = listen(s1, 32);
3578c2ecf20Sopenharmony_ci	if (err < 0) {
3588c2ecf20Sopenharmony_ci		perror("listen s1 failed()");
3598c2ecf20Sopenharmony_ci		return errno;
3608c2ecf20Sopenharmony_ci	}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	addr.sin_port = htons(S2_PORT);
3638c2ecf20Sopenharmony_ci	err = listen(s2, 32);
3648c2ecf20Sopenharmony_ci	if (err < 0) {
3658c2ecf20Sopenharmony_ci		perror("listen s1 failed()");
3668c2ecf20Sopenharmony_ci		return errno;
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	/* Initiate Connect */
3708c2ecf20Sopenharmony_ci	addr.sin_port = htons(S1_PORT);
3718c2ecf20Sopenharmony_ci	err = connect(c1, (struct sockaddr *)&addr, sizeof(addr));
3728c2ecf20Sopenharmony_ci	if (err < 0 && errno != EINPROGRESS) {
3738c2ecf20Sopenharmony_ci		perror("connect c1 failed()");
3748c2ecf20Sopenharmony_ci		return errno;
3758c2ecf20Sopenharmony_ci	}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	addr.sin_port = htons(S2_PORT);
3788c2ecf20Sopenharmony_ci	err = connect(c2, (struct sockaddr *)&addr, sizeof(addr));
3798c2ecf20Sopenharmony_ci	if (err < 0 && errno != EINPROGRESS) {
3808c2ecf20Sopenharmony_ci		perror("connect c2 failed()");
3818c2ecf20Sopenharmony_ci		return errno;
3828c2ecf20Sopenharmony_ci	} else if (err < 0) {
3838c2ecf20Sopenharmony_ci		err = 0;
3848c2ecf20Sopenharmony_ci	}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	/* Accept Connecrtions */
3878c2ecf20Sopenharmony_ci	p1 = accept(s1, NULL, NULL);
3888c2ecf20Sopenharmony_ci	if (p1 < 0) {
3898c2ecf20Sopenharmony_ci		perror("accept s1 failed()");
3908c2ecf20Sopenharmony_ci		return errno;
3918c2ecf20Sopenharmony_ci	}
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	p2 = accept(s2, NULL, NULL);
3948c2ecf20Sopenharmony_ci	if (p2 < 0) {
3958c2ecf20Sopenharmony_ci		perror("accept s1 failed()");
3968c2ecf20Sopenharmony_ci		return errno;
3978c2ecf20Sopenharmony_ci	}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	if (verbose > 1) {
4008c2ecf20Sopenharmony_ci		printf("connected sockets: c1 <-> p1, c2 <-> p2\n");
4018c2ecf20Sopenharmony_ci		printf("cgroups binding: c1(%i) <-> s1(%i) - - - c2(%i) <-> s2(%i)\n",
4028c2ecf20Sopenharmony_ci			c1, s1, c2, s2);
4038c2ecf20Sopenharmony_ci	}
4048c2ecf20Sopenharmony_ci	return 0;
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_cistruct msg_stats {
4088c2ecf20Sopenharmony_ci	size_t bytes_sent;
4098c2ecf20Sopenharmony_ci	size_t bytes_recvd;
4108c2ecf20Sopenharmony_ci	struct timespec start;
4118c2ecf20Sopenharmony_ci	struct timespec end;
4128c2ecf20Sopenharmony_ci};
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_cistatic int msg_loop_sendpage(int fd, int iov_length, int cnt,
4158c2ecf20Sopenharmony_ci			     struct msg_stats *s,
4168c2ecf20Sopenharmony_ci			     struct sockmap_options *opt)
4178c2ecf20Sopenharmony_ci{
4188c2ecf20Sopenharmony_ci	bool drop = opt->drop_expected;
4198c2ecf20Sopenharmony_ci	unsigned char k = 0;
4208c2ecf20Sopenharmony_ci	FILE *file;
4218c2ecf20Sopenharmony_ci	int i, fp;
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	file = tmpfile();
4248c2ecf20Sopenharmony_ci	if (!file) {
4258c2ecf20Sopenharmony_ci		perror("create file for sendpage");
4268c2ecf20Sopenharmony_ci		return 1;
4278c2ecf20Sopenharmony_ci	}
4288c2ecf20Sopenharmony_ci	for (i = 0; i < iov_length * cnt; i++, k++)
4298c2ecf20Sopenharmony_ci		fwrite(&k, sizeof(char), 1, file);
4308c2ecf20Sopenharmony_ci	fflush(file);
4318c2ecf20Sopenharmony_ci	fseek(file, 0, SEEK_SET);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	fp = fileno(file);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	clock_gettime(CLOCK_MONOTONIC, &s->start);
4368c2ecf20Sopenharmony_ci	for (i = 0; i < cnt; i++) {
4378c2ecf20Sopenharmony_ci		int sent;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci		errno = 0;
4408c2ecf20Sopenharmony_ci		sent = sendfile(fd, fp, NULL, iov_length);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci		if (!drop && sent < 0) {
4438c2ecf20Sopenharmony_ci			perror("sendpage loop error");
4448c2ecf20Sopenharmony_ci			fclose(file);
4458c2ecf20Sopenharmony_ci			return sent;
4468c2ecf20Sopenharmony_ci		} else if (drop && sent >= 0) {
4478c2ecf20Sopenharmony_ci			printf("sendpage loop error expected: %i errno %i\n",
4488c2ecf20Sopenharmony_ci			       sent, errno);
4498c2ecf20Sopenharmony_ci			fclose(file);
4508c2ecf20Sopenharmony_ci			return -EIO;
4518c2ecf20Sopenharmony_ci		}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci		if (sent > 0)
4548c2ecf20Sopenharmony_ci			s->bytes_sent += sent;
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci	clock_gettime(CLOCK_MONOTONIC, &s->end);
4578c2ecf20Sopenharmony_ci	fclose(file);
4588c2ecf20Sopenharmony_ci	return 0;
4598c2ecf20Sopenharmony_ci}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_cistatic void msg_free_iov(struct msghdr *msg)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	int i;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	for (i = 0; i < msg->msg_iovlen; i++)
4668c2ecf20Sopenharmony_ci		free(msg->msg_iov[i].iov_base);
4678c2ecf20Sopenharmony_ci	free(msg->msg_iov);
4688c2ecf20Sopenharmony_ci	msg->msg_iov = NULL;
4698c2ecf20Sopenharmony_ci	msg->msg_iovlen = 0;
4708c2ecf20Sopenharmony_ci}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_cistatic int msg_alloc_iov(struct msghdr *msg,
4738c2ecf20Sopenharmony_ci			 int iov_count, int iov_length,
4748c2ecf20Sopenharmony_ci			 bool data, bool xmit)
4758c2ecf20Sopenharmony_ci{
4768c2ecf20Sopenharmony_ci	unsigned char k = 0;
4778c2ecf20Sopenharmony_ci	struct iovec *iov;
4788c2ecf20Sopenharmony_ci	int i;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	iov = calloc(iov_count, sizeof(struct iovec));
4818c2ecf20Sopenharmony_ci	if (!iov)
4828c2ecf20Sopenharmony_ci		return errno;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	for (i = 0; i < iov_count; i++) {
4858c2ecf20Sopenharmony_ci		unsigned char *d = calloc(iov_length, sizeof(char));
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci		if (!d) {
4888c2ecf20Sopenharmony_ci			fprintf(stderr, "iov_count %i/%i OOM\n", i, iov_count);
4898c2ecf20Sopenharmony_ci			goto unwind_iov;
4908c2ecf20Sopenharmony_ci		}
4918c2ecf20Sopenharmony_ci		iov[i].iov_base = d;
4928c2ecf20Sopenharmony_ci		iov[i].iov_len = iov_length;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci		if (data && xmit) {
4958c2ecf20Sopenharmony_ci			int j;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci			for (j = 0; j < iov_length; j++)
4988c2ecf20Sopenharmony_ci				d[j] = k++;
4998c2ecf20Sopenharmony_ci		}
5008c2ecf20Sopenharmony_ci	}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	msg->msg_iov = iov;
5038c2ecf20Sopenharmony_ci	msg->msg_iovlen = iov_count;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	return 0;
5068c2ecf20Sopenharmony_ciunwind_iov:
5078c2ecf20Sopenharmony_ci	for (i--; i >= 0 ; i--)
5088c2ecf20Sopenharmony_ci		free(msg->msg_iov[i].iov_base);
5098c2ecf20Sopenharmony_ci	return -ENOMEM;
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic int msg_verify_data(struct msghdr *msg, int size, int chunk_sz)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	int i, j = 0, bytes_cnt = 0;
5158c2ecf20Sopenharmony_ci	unsigned char k = 0;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	for (i = 0; i < msg->msg_iovlen; i++) {
5188c2ecf20Sopenharmony_ci		unsigned char *d = msg->msg_iov[i].iov_base;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci		/* Special case test for skb ingress + ktls */
5218c2ecf20Sopenharmony_ci		if (i == 0 && txmsg_ktls_skb) {
5228c2ecf20Sopenharmony_ci			if (msg->msg_iov[i].iov_len < 4)
5238c2ecf20Sopenharmony_ci				return -EIO;
5248c2ecf20Sopenharmony_ci			if (memcmp(d, "PASS", 4) != 0) {
5258c2ecf20Sopenharmony_ci				fprintf(stderr,
5268c2ecf20Sopenharmony_ci					"detected skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n",
5278c2ecf20Sopenharmony_ci					i, 0, d[0], d[1], d[2], d[3]);
5288c2ecf20Sopenharmony_ci				return -EIO;
5298c2ecf20Sopenharmony_ci			}
5308c2ecf20Sopenharmony_ci			j = 4; /* advance index past PASS header */
5318c2ecf20Sopenharmony_ci		}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci		for (; j < msg->msg_iov[i].iov_len && size; j++) {
5348c2ecf20Sopenharmony_ci			if (d[j] != k++) {
5358c2ecf20Sopenharmony_ci				fprintf(stderr,
5368c2ecf20Sopenharmony_ci					"detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
5378c2ecf20Sopenharmony_ci					i, j, d[j], k - 1, d[j+1], k);
5388c2ecf20Sopenharmony_ci				return -EIO;
5398c2ecf20Sopenharmony_ci			}
5408c2ecf20Sopenharmony_ci			bytes_cnt++;
5418c2ecf20Sopenharmony_ci			if (bytes_cnt == chunk_sz) {
5428c2ecf20Sopenharmony_ci				k = 0;
5438c2ecf20Sopenharmony_ci				bytes_cnt = 0;
5448c2ecf20Sopenharmony_ci			}
5458c2ecf20Sopenharmony_ci			size--;
5468c2ecf20Sopenharmony_ci		}
5478c2ecf20Sopenharmony_ci	}
5488c2ecf20Sopenharmony_ci	return 0;
5498c2ecf20Sopenharmony_ci}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_cistatic int msg_loop(int fd, int iov_count, int iov_length, int cnt,
5528c2ecf20Sopenharmony_ci		    struct msg_stats *s, bool tx,
5538c2ecf20Sopenharmony_ci		    struct sockmap_options *opt)
5548c2ecf20Sopenharmony_ci{
5558c2ecf20Sopenharmony_ci	struct msghdr msg = {0}, msg_peek = {0};
5568c2ecf20Sopenharmony_ci	int err, i, flags = MSG_NOSIGNAL;
5578c2ecf20Sopenharmony_ci	bool drop = opt->drop_expected;
5588c2ecf20Sopenharmony_ci	bool data = opt->data_test;
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	err = msg_alloc_iov(&msg, iov_count, iov_length, data, tx);
5618c2ecf20Sopenharmony_ci	if (err)
5628c2ecf20Sopenharmony_ci		goto out_errno;
5638c2ecf20Sopenharmony_ci	if (peek_flag) {
5648c2ecf20Sopenharmony_ci		err = msg_alloc_iov(&msg_peek, iov_count, iov_length, data, tx);
5658c2ecf20Sopenharmony_ci		if (err)
5668c2ecf20Sopenharmony_ci			goto out_errno;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	if (tx) {
5708c2ecf20Sopenharmony_ci		clock_gettime(CLOCK_MONOTONIC, &s->start);
5718c2ecf20Sopenharmony_ci		for (i = 0; i < cnt; i++) {
5728c2ecf20Sopenharmony_ci			int sent;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci			errno = 0;
5758c2ecf20Sopenharmony_ci			sent = sendmsg(fd, &msg, flags);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci			if (!drop && sent < 0) {
5788c2ecf20Sopenharmony_ci				perror("sendmsg loop error");
5798c2ecf20Sopenharmony_ci				goto out_errno;
5808c2ecf20Sopenharmony_ci			} else if (drop && sent >= 0) {
5818c2ecf20Sopenharmony_ci				fprintf(stderr,
5828c2ecf20Sopenharmony_ci					"sendmsg loop error expected: %i errno %i\n",
5838c2ecf20Sopenharmony_ci					sent, errno);
5848c2ecf20Sopenharmony_ci				errno = -EIO;
5858c2ecf20Sopenharmony_ci				goto out_errno;
5868c2ecf20Sopenharmony_ci			}
5878c2ecf20Sopenharmony_ci			if (sent > 0)
5888c2ecf20Sopenharmony_ci				s->bytes_sent += sent;
5898c2ecf20Sopenharmony_ci		}
5908c2ecf20Sopenharmony_ci		clock_gettime(CLOCK_MONOTONIC, &s->end);
5918c2ecf20Sopenharmony_ci	} else {
5928c2ecf20Sopenharmony_ci		int slct, recvp = 0, recv, max_fd = fd;
5938c2ecf20Sopenharmony_ci		float total_bytes, txmsg_pop_total;
5948c2ecf20Sopenharmony_ci		int fd_flags = O_NONBLOCK;
5958c2ecf20Sopenharmony_ci		struct timeval timeout;
5968c2ecf20Sopenharmony_ci		fd_set w;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci		fcntl(fd, fd_flags);
5998c2ecf20Sopenharmony_ci		/* Account for pop bytes noting each iteration of apply will
6008c2ecf20Sopenharmony_ci		 * call msg_pop_data helper so we need to account for this
6018c2ecf20Sopenharmony_ci		 * by calculating the number of apply iterations. Note user
6028c2ecf20Sopenharmony_ci		 * of the tool can create cases where no data is sent by
6038c2ecf20Sopenharmony_ci		 * manipulating pop/push/pull/etc. For example txmsg_apply 1
6048c2ecf20Sopenharmony_ci		 * with txmsg_pop 1 will try to apply 1B at a time but each
6058c2ecf20Sopenharmony_ci		 * iteration will then pop 1B so no data will ever be sent.
6068c2ecf20Sopenharmony_ci		 * This is really only useful for testing edge cases in code
6078c2ecf20Sopenharmony_ci		 * paths.
6088c2ecf20Sopenharmony_ci		 */
6098c2ecf20Sopenharmony_ci		total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
6108c2ecf20Sopenharmony_ci		if (txmsg_apply)
6118c2ecf20Sopenharmony_ci			txmsg_pop_total = txmsg_pop * (total_bytes / txmsg_apply);
6128c2ecf20Sopenharmony_ci		else
6138c2ecf20Sopenharmony_ci			txmsg_pop_total = txmsg_pop * cnt;
6148c2ecf20Sopenharmony_ci		total_bytes -= txmsg_pop_total;
6158c2ecf20Sopenharmony_ci		err = clock_gettime(CLOCK_MONOTONIC, &s->start);
6168c2ecf20Sopenharmony_ci		if (err < 0)
6178c2ecf20Sopenharmony_ci			perror("recv start time");
6188c2ecf20Sopenharmony_ci		while (s->bytes_recvd < total_bytes) {
6198c2ecf20Sopenharmony_ci			if (txmsg_cork) {
6208c2ecf20Sopenharmony_ci				timeout.tv_sec = 0;
6218c2ecf20Sopenharmony_ci				timeout.tv_usec = 300000;
6228c2ecf20Sopenharmony_ci			} else {
6238c2ecf20Sopenharmony_ci				timeout.tv_sec = 3;
6248c2ecf20Sopenharmony_ci				timeout.tv_usec = 0;
6258c2ecf20Sopenharmony_ci			}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci			/* FD sets */
6288c2ecf20Sopenharmony_ci			FD_ZERO(&w);
6298c2ecf20Sopenharmony_ci			FD_SET(fd, &w);
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci			slct = select(max_fd + 1, &w, NULL, NULL, &timeout);
6328c2ecf20Sopenharmony_ci			if (slct == -1) {
6338c2ecf20Sopenharmony_ci				perror("select()");
6348c2ecf20Sopenharmony_ci				clock_gettime(CLOCK_MONOTONIC, &s->end);
6358c2ecf20Sopenharmony_ci				goto out_errno;
6368c2ecf20Sopenharmony_ci			} else if (!slct) {
6378c2ecf20Sopenharmony_ci				if (opt->verbose)
6388c2ecf20Sopenharmony_ci					fprintf(stderr, "unexpected timeout: recved %zu/%f pop_total %f\n", s->bytes_recvd, total_bytes, txmsg_pop_total);
6398c2ecf20Sopenharmony_ci				errno = -EIO;
6408c2ecf20Sopenharmony_ci				clock_gettime(CLOCK_MONOTONIC, &s->end);
6418c2ecf20Sopenharmony_ci				goto out_errno;
6428c2ecf20Sopenharmony_ci			}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci			errno = 0;
6458c2ecf20Sopenharmony_ci			if (peek_flag) {
6468c2ecf20Sopenharmony_ci				flags |= MSG_PEEK;
6478c2ecf20Sopenharmony_ci				recvp = recvmsg(fd, &msg_peek, flags);
6488c2ecf20Sopenharmony_ci				if (recvp < 0) {
6498c2ecf20Sopenharmony_ci					if (errno != EWOULDBLOCK) {
6508c2ecf20Sopenharmony_ci						clock_gettime(CLOCK_MONOTONIC, &s->end);
6518c2ecf20Sopenharmony_ci						goto out_errno;
6528c2ecf20Sopenharmony_ci					}
6538c2ecf20Sopenharmony_ci				}
6548c2ecf20Sopenharmony_ci				flags = 0;
6558c2ecf20Sopenharmony_ci			}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci			recv = recvmsg(fd, &msg, flags);
6588c2ecf20Sopenharmony_ci			if (recv < 0) {
6598c2ecf20Sopenharmony_ci				if (errno != EWOULDBLOCK) {
6608c2ecf20Sopenharmony_ci					clock_gettime(CLOCK_MONOTONIC, &s->end);
6618c2ecf20Sopenharmony_ci					perror("recv failed()");
6628c2ecf20Sopenharmony_ci					goto out_errno;
6638c2ecf20Sopenharmony_ci				}
6648c2ecf20Sopenharmony_ci			}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci			s->bytes_recvd += recv;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci			if (data) {
6698c2ecf20Sopenharmony_ci				int chunk_sz = opt->sendpage ?
6708c2ecf20Sopenharmony_ci						iov_length * cnt :
6718c2ecf20Sopenharmony_ci						iov_length * iov_count;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci				errno = msg_verify_data(&msg, recv, chunk_sz);
6748c2ecf20Sopenharmony_ci				if (errno) {
6758c2ecf20Sopenharmony_ci					perror("data verify msg failed");
6768c2ecf20Sopenharmony_ci					goto out_errno;
6778c2ecf20Sopenharmony_ci				}
6788c2ecf20Sopenharmony_ci				if (recvp) {
6798c2ecf20Sopenharmony_ci					errno = msg_verify_data(&msg_peek,
6808c2ecf20Sopenharmony_ci								recvp,
6818c2ecf20Sopenharmony_ci								chunk_sz);
6828c2ecf20Sopenharmony_ci					if (errno) {
6838c2ecf20Sopenharmony_ci						perror("data verify msg_peek failed");
6848c2ecf20Sopenharmony_ci						goto out_errno;
6858c2ecf20Sopenharmony_ci					}
6868c2ecf20Sopenharmony_ci				}
6878c2ecf20Sopenharmony_ci			}
6888c2ecf20Sopenharmony_ci		}
6898c2ecf20Sopenharmony_ci		clock_gettime(CLOCK_MONOTONIC, &s->end);
6908c2ecf20Sopenharmony_ci	}
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	msg_free_iov(&msg);
6938c2ecf20Sopenharmony_ci	msg_free_iov(&msg_peek);
6948c2ecf20Sopenharmony_ci	return err;
6958c2ecf20Sopenharmony_ciout_errno:
6968c2ecf20Sopenharmony_ci	msg_free_iov(&msg);
6978c2ecf20Sopenharmony_ci	msg_free_iov(&msg_peek);
6988c2ecf20Sopenharmony_ci	return errno;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_cistatic float giga = 1000000000;
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_cistatic inline float sentBps(struct msg_stats s)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	return s.bytes_sent / (s.end.tv_sec - s.start.tv_sec);
7068c2ecf20Sopenharmony_ci}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_cistatic inline float recvdBps(struct msg_stats s)
7098c2ecf20Sopenharmony_ci{
7108c2ecf20Sopenharmony_ci	return s.bytes_recvd / (s.end.tv_sec - s.start.tv_sec);
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic int sendmsg_test(struct sockmap_options *opt)
7148c2ecf20Sopenharmony_ci{
7158c2ecf20Sopenharmony_ci	float sent_Bps = 0, recvd_Bps = 0;
7168c2ecf20Sopenharmony_ci	int rx_fd, txpid, rxpid, err = 0;
7178c2ecf20Sopenharmony_ci	struct msg_stats s = {0};
7188c2ecf20Sopenharmony_ci	int iov_count = opt->iov_count;
7198c2ecf20Sopenharmony_ci	int iov_buf = opt->iov_length;
7208c2ecf20Sopenharmony_ci	int rx_status, tx_status;
7218c2ecf20Sopenharmony_ci	int cnt = opt->rate;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	errno = 0;
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	if (opt->base)
7268c2ecf20Sopenharmony_ci		rx_fd = p1;
7278c2ecf20Sopenharmony_ci	else
7288c2ecf20Sopenharmony_ci		rx_fd = p2;
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (ktls) {
7318c2ecf20Sopenharmony_ci		/* Redirecting into non-TLS socket which sends into a TLS
7328c2ecf20Sopenharmony_ci		 * socket is not a valid test. So in this case lets not
7338c2ecf20Sopenharmony_ci		 * enable kTLS but still run the test.
7348c2ecf20Sopenharmony_ci		 */
7358c2ecf20Sopenharmony_ci		if (!txmsg_redir || (txmsg_redir && txmsg_ingress)) {
7368c2ecf20Sopenharmony_ci			err = sockmap_init_ktls(opt->verbose, rx_fd);
7378c2ecf20Sopenharmony_ci			if (err)
7388c2ecf20Sopenharmony_ci				return err;
7398c2ecf20Sopenharmony_ci		}
7408c2ecf20Sopenharmony_ci		err = sockmap_init_ktls(opt->verbose, c1);
7418c2ecf20Sopenharmony_ci		if (err)
7428c2ecf20Sopenharmony_ci			return err;
7438c2ecf20Sopenharmony_ci	}
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	rxpid = fork();
7468c2ecf20Sopenharmony_ci	if (rxpid == 0) {
7478c2ecf20Sopenharmony_ci		iov_buf -= (txmsg_pop - txmsg_start_pop + 1);
7488c2ecf20Sopenharmony_ci		if (opt->drop_expected || txmsg_ktls_skb_drop)
7498c2ecf20Sopenharmony_ci			_exit(0);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci		if (!iov_buf) /* zero bytes sent case */
7528c2ecf20Sopenharmony_ci			_exit(0);
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci		if (opt->sendpage)
7558c2ecf20Sopenharmony_ci			iov_count = 1;
7568c2ecf20Sopenharmony_ci		err = msg_loop(rx_fd, iov_count, iov_buf,
7578c2ecf20Sopenharmony_ci			       cnt, &s, false, opt);
7588c2ecf20Sopenharmony_ci		if (opt->verbose > 1)
7598c2ecf20Sopenharmony_ci			fprintf(stderr,
7608c2ecf20Sopenharmony_ci				"msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
7618c2ecf20Sopenharmony_ci				iov_count, iov_buf, cnt, err);
7628c2ecf20Sopenharmony_ci		if (s.end.tv_sec - s.start.tv_sec) {
7638c2ecf20Sopenharmony_ci			sent_Bps = sentBps(s);
7648c2ecf20Sopenharmony_ci			recvd_Bps = recvdBps(s);
7658c2ecf20Sopenharmony_ci		}
7668c2ecf20Sopenharmony_ci		if (opt->verbose > 1)
7678c2ecf20Sopenharmony_ci			fprintf(stdout,
7688c2ecf20Sopenharmony_ci				"rx_sendmsg: TX: %zuB %fB/s %fGB/s RX: %zuB %fB/s %fGB/s %s\n",
7698c2ecf20Sopenharmony_ci				s.bytes_sent, sent_Bps, sent_Bps/giga,
7708c2ecf20Sopenharmony_ci				s.bytes_recvd, recvd_Bps, recvd_Bps/giga,
7718c2ecf20Sopenharmony_ci				peek_flag ? "(peek_msg)" : "");
7728c2ecf20Sopenharmony_ci		if (err && txmsg_cork)
7738c2ecf20Sopenharmony_ci			err = 0;
7748c2ecf20Sopenharmony_ci		exit(err ? 1 : 0);
7758c2ecf20Sopenharmony_ci	} else if (rxpid == -1) {
7768c2ecf20Sopenharmony_ci		perror("msg_loop_rx");
7778c2ecf20Sopenharmony_ci		return errno;
7788c2ecf20Sopenharmony_ci	}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	txpid = fork();
7818c2ecf20Sopenharmony_ci	if (txpid == 0) {
7828c2ecf20Sopenharmony_ci		if (opt->sendpage)
7838c2ecf20Sopenharmony_ci			err = msg_loop_sendpage(c1, iov_buf, cnt, &s, opt);
7848c2ecf20Sopenharmony_ci		else
7858c2ecf20Sopenharmony_ci			err = msg_loop(c1, iov_count, iov_buf,
7868c2ecf20Sopenharmony_ci				       cnt, &s, true, opt);
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci		if (err)
7898c2ecf20Sopenharmony_ci			fprintf(stderr,
7908c2ecf20Sopenharmony_ci				"msg_loop_tx: iov_count %i iov_buf %i cnt %i err %i\n",
7918c2ecf20Sopenharmony_ci				iov_count, iov_buf, cnt, err);
7928c2ecf20Sopenharmony_ci		if (s.end.tv_sec - s.start.tv_sec) {
7938c2ecf20Sopenharmony_ci			sent_Bps = sentBps(s);
7948c2ecf20Sopenharmony_ci			recvd_Bps = recvdBps(s);
7958c2ecf20Sopenharmony_ci		}
7968c2ecf20Sopenharmony_ci		if (opt->verbose > 1)
7978c2ecf20Sopenharmony_ci			fprintf(stdout,
7988c2ecf20Sopenharmony_ci				"tx_sendmsg: TX: %zuB %fB/s %f GB/s RX: %zuB %fB/s %fGB/s\n",
7998c2ecf20Sopenharmony_ci				s.bytes_sent, sent_Bps, sent_Bps/giga,
8008c2ecf20Sopenharmony_ci				s.bytes_recvd, recvd_Bps, recvd_Bps/giga);
8018c2ecf20Sopenharmony_ci		exit(err ? 1 : 0);
8028c2ecf20Sopenharmony_ci	} else if (txpid == -1) {
8038c2ecf20Sopenharmony_ci		perror("msg_loop_tx");
8048c2ecf20Sopenharmony_ci		return errno;
8058c2ecf20Sopenharmony_ci	}
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	assert(waitpid(rxpid, &rx_status, 0) == rxpid);
8088c2ecf20Sopenharmony_ci	assert(waitpid(txpid, &tx_status, 0) == txpid);
8098c2ecf20Sopenharmony_ci	if (WIFEXITED(rx_status)) {
8108c2ecf20Sopenharmony_ci		err = WEXITSTATUS(rx_status);
8118c2ecf20Sopenharmony_ci		if (err) {
8128c2ecf20Sopenharmony_ci			fprintf(stderr, "rx thread exited with err %d.\n", err);
8138c2ecf20Sopenharmony_ci			goto out;
8148c2ecf20Sopenharmony_ci		}
8158c2ecf20Sopenharmony_ci	}
8168c2ecf20Sopenharmony_ci	if (WIFEXITED(tx_status)) {
8178c2ecf20Sopenharmony_ci		err = WEXITSTATUS(tx_status);
8188c2ecf20Sopenharmony_ci		if (err)
8198c2ecf20Sopenharmony_ci			fprintf(stderr, "tx thread exited with err %d.\n", err);
8208c2ecf20Sopenharmony_ci	}
8218c2ecf20Sopenharmony_ciout:
8228c2ecf20Sopenharmony_ci	return err;
8238c2ecf20Sopenharmony_ci}
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_cistatic int forever_ping_pong(int rate, struct sockmap_options *opt)
8268c2ecf20Sopenharmony_ci{
8278c2ecf20Sopenharmony_ci	struct timeval timeout;
8288c2ecf20Sopenharmony_ci	char buf[1024] = {0};
8298c2ecf20Sopenharmony_ci	int sc;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	timeout.tv_sec = 10;
8328c2ecf20Sopenharmony_ci	timeout.tv_usec = 0;
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	/* Ping/Pong data from client to server */
8358c2ecf20Sopenharmony_ci	sc = send(c1, buf, sizeof(buf), 0);
8368c2ecf20Sopenharmony_ci	if (sc < 0) {
8378c2ecf20Sopenharmony_ci		perror("send failed()");
8388c2ecf20Sopenharmony_ci		return sc;
8398c2ecf20Sopenharmony_ci	}
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	do {
8428c2ecf20Sopenharmony_ci		int s, rc, i, max_fd = p2;
8438c2ecf20Sopenharmony_ci		fd_set w;
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci		/* FD sets */
8468c2ecf20Sopenharmony_ci		FD_ZERO(&w);
8478c2ecf20Sopenharmony_ci		FD_SET(c1, &w);
8488c2ecf20Sopenharmony_ci		FD_SET(c2, &w);
8498c2ecf20Sopenharmony_ci		FD_SET(p1, &w);
8508c2ecf20Sopenharmony_ci		FD_SET(p2, &w);
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci		s = select(max_fd + 1, &w, NULL, NULL, &timeout);
8538c2ecf20Sopenharmony_ci		if (s == -1) {
8548c2ecf20Sopenharmony_ci			perror("select()");
8558c2ecf20Sopenharmony_ci			break;
8568c2ecf20Sopenharmony_ci		} else if (!s) {
8578c2ecf20Sopenharmony_ci			fprintf(stderr, "unexpected timeout\n");
8588c2ecf20Sopenharmony_ci			break;
8598c2ecf20Sopenharmony_ci		}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci		for (i = 0; i <= max_fd && s > 0; ++i) {
8628c2ecf20Sopenharmony_ci			if (!FD_ISSET(i, &w))
8638c2ecf20Sopenharmony_ci				continue;
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci			s--;
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci			rc = recv(i, buf, sizeof(buf), 0);
8688c2ecf20Sopenharmony_ci			if (rc < 0) {
8698c2ecf20Sopenharmony_ci				if (errno != EWOULDBLOCK) {
8708c2ecf20Sopenharmony_ci					perror("recv failed()");
8718c2ecf20Sopenharmony_ci					return rc;
8728c2ecf20Sopenharmony_ci				}
8738c2ecf20Sopenharmony_ci			}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci			if (rc == 0) {
8768c2ecf20Sopenharmony_ci				close(i);
8778c2ecf20Sopenharmony_ci				break;
8788c2ecf20Sopenharmony_ci			}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci			sc = send(i, buf, rc, 0);
8818c2ecf20Sopenharmony_ci			if (sc < 0) {
8828c2ecf20Sopenharmony_ci				perror("send failed()");
8838c2ecf20Sopenharmony_ci				return sc;
8848c2ecf20Sopenharmony_ci			}
8858c2ecf20Sopenharmony_ci		}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci		if (rate)
8888c2ecf20Sopenharmony_ci			sleep(rate);
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci		if (opt->verbose) {
8918c2ecf20Sopenharmony_ci			printf(".");
8928c2ecf20Sopenharmony_ci			fflush(stdout);
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci		}
8958c2ecf20Sopenharmony_ci	} while (running);
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	return 0;
8988c2ecf20Sopenharmony_ci}
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_cienum {
9018c2ecf20Sopenharmony_ci	SELFTESTS,
9028c2ecf20Sopenharmony_ci	PING_PONG,
9038c2ecf20Sopenharmony_ci	SENDMSG,
9048c2ecf20Sopenharmony_ci	BASE,
9058c2ecf20Sopenharmony_ci	BASE_SENDPAGE,
9068c2ecf20Sopenharmony_ci	SENDPAGE,
9078c2ecf20Sopenharmony_ci};
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_cistatic int run_options(struct sockmap_options *options, int cg_fd,  int test)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	int i, key, next_key, err, tx_prog_fd = -1, zero = 0;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	/* If base test skip BPF setup */
9148c2ecf20Sopenharmony_ci	if (test == BASE || test == BASE_SENDPAGE)
9158c2ecf20Sopenharmony_ci		goto run;
9168c2ecf20Sopenharmony_ci
9178c2ecf20Sopenharmony_ci	/* Attach programs to sockmap */
9188c2ecf20Sopenharmony_ci	if (!txmsg_omit_skb_parser) {
9198c2ecf20Sopenharmony_ci		err = bpf_prog_attach(prog_fd[0], map_fd[0],
9208c2ecf20Sopenharmony_ci				      BPF_SK_SKB_STREAM_PARSER, 0);
9218c2ecf20Sopenharmony_ci		if (err) {
9228c2ecf20Sopenharmony_ci			fprintf(stderr,
9238c2ecf20Sopenharmony_ci				"ERROR: bpf_prog_attach (sockmap %i->%i): %d (%s)\n",
9248c2ecf20Sopenharmony_ci				prog_fd[0], map_fd[0], err, strerror(errno));
9258c2ecf20Sopenharmony_ci			return err;
9268c2ecf20Sopenharmony_ci		}
9278c2ecf20Sopenharmony_ci	}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	err = bpf_prog_attach(prog_fd[1], map_fd[0],
9308c2ecf20Sopenharmony_ci				BPF_SK_SKB_STREAM_VERDICT, 0);
9318c2ecf20Sopenharmony_ci	if (err) {
9328c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: bpf_prog_attach (sockmap): %d (%s)\n",
9338c2ecf20Sopenharmony_ci			err, strerror(errno));
9348c2ecf20Sopenharmony_ci		return err;
9358c2ecf20Sopenharmony_ci	}
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci	/* Attach programs to TLS sockmap */
9388c2ecf20Sopenharmony_ci	if (txmsg_ktls_skb) {
9398c2ecf20Sopenharmony_ci		if (!txmsg_omit_skb_parser) {
9408c2ecf20Sopenharmony_ci			err = bpf_prog_attach(prog_fd[0], map_fd[8],
9418c2ecf20Sopenharmony_ci					      BPF_SK_SKB_STREAM_PARSER, 0);
9428c2ecf20Sopenharmony_ci			if (err) {
9438c2ecf20Sopenharmony_ci				fprintf(stderr,
9448c2ecf20Sopenharmony_ci					"ERROR: bpf_prog_attach (TLS sockmap %i->%i): %d (%s)\n",
9458c2ecf20Sopenharmony_ci					prog_fd[0], map_fd[8], err, strerror(errno));
9468c2ecf20Sopenharmony_ci				return err;
9478c2ecf20Sopenharmony_ci			}
9488c2ecf20Sopenharmony_ci		}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci		err = bpf_prog_attach(prog_fd[2], map_fd[8],
9518c2ecf20Sopenharmony_ci				      BPF_SK_SKB_STREAM_VERDICT, 0);
9528c2ecf20Sopenharmony_ci		if (err) {
9538c2ecf20Sopenharmony_ci			fprintf(stderr, "ERROR: bpf_prog_attach (TLS sockmap): %d (%s)\n",
9548c2ecf20Sopenharmony_ci				err, strerror(errno));
9558c2ecf20Sopenharmony_ci			return err;
9568c2ecf20Sopenharmony_ci		}
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	/* Attach to cgroups */
9608c2ecf20Sopenharmony_ci	err = bpf_prog_attach(prog_fd[3], cg_fd, BPF_CGROUP_SOCK_OPS, 0);
9618c2ecf20Sopenharmony_ci	if (err) {
9628c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: bpf_prog_attach (groups): %d (%s)\n",
9638c2ecf20Sopenharmony_ci			err, strerror(errno));
9648c2ecf20Sopenharmony_ci		return err;
9658c2ecf20Sopenharmony_ci	}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_cirun:
9688c2ecf20Sopenharmony_ci	err = sockmap_init_sockets(options->verbose);
9698c2ecf20Sopenharmony_ci	if (err) {
9708c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: test socket failed: %d\n", err);
9718c2ecf20Sopenharmony_ci		goto out;
9728c2ecf20Sopenharmony_ci	}
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	/* Attach txmsg program to sockmap */
9758c2ecf20Sopenharmony_ci	if (txmsg_pass)
9768c2ecf20Sopenharmony_ci		tx_prog_fd = prog_fd[4];
9778c2ecf20Sopenharmony_ci	else if (txmsg_redir)
9788c2ecf20Sopenharmony_ci		tx_prog_fd = prog_fd[5];
9798c2ecf20Sopenharmony_ci	else if (txmsg_apply)
9808c2ecf20Sopenharmony_ci		tx_prog_fd = prog_fd[6];
9818c2ecf20Sopenharmony_ci	else if (txmsg_cork)
9828c2ecf20Sopenharmony_ci		tx_prog_fd = prog_fd[7];
9838c2ecf20Sopenharmony_ci	else if (txmsg_drop)
9848c2ecf20Sopenharmony_ci		tx_prog_fd = prog_fd[8];
9858c2ecf20Sopenharmony_ci	else
9868c2ecf20Sopenharmony_ci		tx_prog_fd = 0;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	if (tx_prog_fd) {
9898c2ecf20Sopenharmony_ci		int redir_fd, i = 0;
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci		err = bpf_prog_attach(tx_prog_fd,
9928c2ecf20Sopenharmony_ci				      map_fd[1], BPF_SK_MSG_VERDICT, 0);
9938c2ecf20Sopenharmony_ci		if (err) {
9948c2ecf20Sopenharmony_ci			fprintf(stderr,
9958c2ecf20Sopenharmony_ci				"ERROR: bpf_prog_attach (txmsg): %d (%s)\n",
9968c2ecf20Sopenharmony_ci				err, strerror(errno));
9978c2ecf20Sopenharmony_ci			goto out;
9988c2ecf20Sopenharmony_ci		}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd[1], &i, &c1, BPF_ANY);
10018c2ecf20Sopenharmony_ci		if (err) {
10028c2ecf20Sopenharmony_ci			fprintf(stderr,
10038c2ecf20Sopenharmony_ci				"ERROR: bpf_map_update_elem (txmsg):  %d (%s\n",
10048c2ecf20Sopenharmony_ci				err, strerror(errno));
10058c2ecf20Sopenharmony_ci			goto out;
10068c2ecf20Sopenharmony_ci		}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci		if (txmsg_redir)
10098c2ecf20Sopenharmony_ci			redir_fd = c2;
10108c2ecf20Sopenharmony_ci		else
10118c2ecf20Sopenharmony_ci			redir_fd = c1;
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd[2], &i, &redir_fd, BPF_ANY);
10148c2ecf20Sopenharmony_ci		if (err) {
10158c2ecf20Sopenharmony_ci			fprintf(stderr,
10168c2ecf20Sopenharmony_ci				"ERROR: bpf_map_update_elem (txmsg):  %d (%s\n",
10178c2ecf20Sopenharmony_ci				err, strerror(errno));
10188c2ecf20Sopenharmony_ci			goto out;
10198c2ecf20Sopenharmony_ci		}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci		if (txmsg_apply) {
10228c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[3],
10238c2ecf20Sopenharmony_ci						  &i, &txmsg_apply, BPF_ANY);
10248c2ecf20Sopenharmony_ci			if (err) {
10258c2ecf20Sopenharmony_ci				fprintf(stderr,
10268c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (apply_bytes):  %d (%s\n",
10278c2ecf20Sopenharmony_ci					err, strerror(errno));
10288c2ecf20Sopenharmony_ci				goto out;
10298c2ecf20Sopenharmony_ci			}
10308c2ecf20Sopenharmony_ci		}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci		if (txmsg_cork) {
10338c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[4],
10348c2ecf20Sopenharmony_ci						  &i, &txmsg_cork, BPF_ANY);
10358c2ecf20Sopenharmony_ci			if (err) {
10368c2ecf20Sopenharmony_ci				fprintf(stderr,
10378c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (cork_bytes):  %d (%s\n",
10388c2ecf20Sopenharmony_ci					err, strerror(errno));
10398c2ecf20Sopenharmony_ci				goto out;
10408c2ecf20Sopenharmony_ci			}
10418c2ecf20Sopenharmony_ci		}
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci		if (txmsg_start) {
10448c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[5],
10458c2ecf20Sopenharmony_ci						  &i, &txmsg_start, BPF_ANY);
10468c2ecf20Sopenharmony_ci			if (err) {
10478c2ecf20Sopenharmony_ci				fprintf(stderr,
10488c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (txmsg_start):  %d (%s)\n",
10498c2ecf20Sopenharmony_ci					err, strerror(errno));
10508c2ecf20Sopenharmony_ci				goto out;
10518c2ecf20Sopenharmony_ci			}
10528c2ecf20Sopenharmony_ci		}
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci		if (txmsg_end) {
10558c2ecf20Sopenharmony_ci			i = 1;
10568c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[5],
10578c2ecf20Sopenharmony_ci						  &i, &txmsg_end, BPF_ANY);
10588c2ecf20Sopenharmony_ci			if (err) {
10598c2ecf20Sopenharmony_ci				fprintf(stderr,
10608c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (txmsg_end):  %d (%s)\n",
10618c2ecf20Sopenharmony_ci					err, strerror(errno));
10628c2ecf20Sopenharmony_ci				goto out;
10638c2ecf20Sopenharmony_ci			}
10648c2ecf20Sopenharmony_ci		}
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci		if (txmsg_start_push) {
10678c2ecf20Sopenharmony_ci			i = 2;
10688c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[5],
10698c2ecf20Sopenharmony_ci						  &i, &txmsg_start_push, BPF_ANY);
10708c2ecf20Sopenharmony_ci			if (err) {
10718c2ecf20Sopenharmony_ci				fprintf(stderr,
10728c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (txmsg_start_push):  %d (%s)\n",
10738c2ecf20Sopenharmony_ci					err, strerror(errno));
10748c2ecf20Sopenharmony_ci				goto out;
10758c2ecf20Sopenharmony_ci			}
10768c2ecf20Sopenharmony_ci		}
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci		if (txmsg_end_push) {
10798c2ecf20Sopenharmony_ci			i = 3;
10808c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[5],
10818c2ecf20Sopenharmony_ci						  &i, &txmsg_end_push, BPF_ANY);
10828c2ecf20Sopenharmony_ci			if (err) {
10838c2ecf20Sopenharmony_ci				fprintf(stderr,
10848c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem %i@%i (txmsg_end_push):  %d (%s)\n",
10858c2ecf20Sopenharmony_ci					txmsg_end_push, i, err, strerror(errno));
10868c2ecf20Sopenharmony_ci				goto out;
10878c2ecf20Sopenharmony_ci			}
10888c2ecf20Sopenharmony_ci		}
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci		if (txmsg_start_pop) {
10918c2ecf20Sopenharmony_ci			i = 4;
10928c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[5],
10938c2ecf20Sopenharmony_ci						  &i, &txmsg_start_pop, BPF_ANY);
10948c2ecf20Sopenharmony_ci			if (err) {
10958c2ecf20Sopenharmony_ci				fprintf(stderr,
10968c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem %i@%i (txmsg_start_pop):  %d (%s)\n",
10978c2ecf20Sopenharmony_ci					txmsg_start_pop, i, err, strerror(errno));
10988c2ecf20Sopenharmony_ci				goto out;
10998c2ecf20Sopenharmony_ci			}
11008c2ecf20Sopenharmony_ci		} else {
11018c2ecf20Sopenharmony_ci			i = 4;
11028c2ecf20Sopenharmony_ci			bpf_map_update_elem(map_fd[5],
11038c2ecf20Sopenharmony_ci						  &i, &txmsg_start_pop, BPF_ANY);
11048c2ecf20Sopenharmony_ci		}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci		if (txmsg_pop) {
11078c2ecf20Sopenharmony_ci			i = 5;
11088c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[5],
11098c2ecf20Sopenharmony_ci						  &i, &txmsg_pop, BPF_ANY);
11108c2ecf20Sopenharmony_ci			if (err) {
11118c2ecf20Sopenharmony_ci				fprintf(stderr,
11128c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem %i@%i (txmsg_pop):  %d (%s)\n",
11138c2ecf20Sopenharmony_ci					txmsg_pop, i, err, strerror(errno));
11148c2ecf20Sopenharmony_ci				goto out;
11158c2ecf20Sopenharmony_ci			}
11168c2ecf20Sopenharmony_ci		} else {
11178c2ecf20Sopenharmony_ci			i = 5;
11188c2ecf20Sopenharmony_ci			bpf_map_update_elem(map_fd[5],
11198c2ecf20Sopenharmony_ci					    &i, &txmsg_pop, BPF_ANY);
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci		}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci		if (txmsg_ingress) {
11248c2ecf20Sopenharmony_ci			int in = BPF_F_INGRESS;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci			i = 0;
11278c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[6], &i, &in, BPF_ANY);
11288c2ecf20Sopenharmony_ci			if (err) {
11298c2ecf20Sopenharmony_ci				fprintf(stderr,
11308c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
11318c2ecf20Sopenharmony_ci					err, strerror(errno));
11328c2ecf20Sopenharmony_ci			}
11338c2ecf20Sopenharmony_ci			i = 1;
11348c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[1], &i, &p1, BPF_ANY);
11358c2ecf20Sopenharmony_ci			if (err) {
11368c2ecf20Sopenharmony_ci				fprintf(stderr,
11378c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (p1 txmsg): %d (%s)\n",
11388c2ecf20Sopenharmony_ci					err, strerror(errno));
11398c2ecf20Sopenharmony_ci			}
11408c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[2], &i, &p1, BPF_ANY);
11418c2ecf20Sopenharmony_ci			if (err) {
11428c2ecf20Sopenharmony_ci				fprintf(stderr,
11438c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (p1 redir): %d (%s)\n",
11448c2ecf20Sopenharmony_ci					err, strerror(errno));
11458c2ecf20Sopenharmony_ci			}
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci			i = 2;
11488c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[2], &i, &p2, BPF_ANY);
11498c2ecf20Sopenharmony_ci			if (err) {
11508c2ecf20Sopenharmony_ci				fprintf(stderr,
11518c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (p2 txmsg): %d (%s)\n",
11528c2ecf20Sopenharmony_ci					err, strerror(errno));
11538c2ecf20Sopenharmony_ci			}
11548c2ecf20Sopenharmony_ci		}
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci		if (txmsg_ktls_skb) {
11578c2ecf20Sopenharmony_ci			int ingress = BPF_F_INGRESS;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci			i = 0;
11608c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[8], &i, &p2, BPF_ANY);
11618c2ecf20Sopenharmony_ci			if (err) {
11628c2ecf20Sopenharmony_ci				fprintf(stderr,
11638c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
11648c2ecf20Sopenharmony_ci					err, strerror(errno));
11658c2ecf20Sopenharmony_ci			}
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci			if (txmsg_ktls_skb_redir) {
11688c2ecf20Sopenharmony_ci				i = 1;
11698c2ecf20Sopenharmony_ci				err = bpf_map_update_elem(map_fd[7],
11708c2ecf20Sopenharmony_ci							  &i, &ingress, BPF_ANY);
11718c2ecf20Sopenharmony_ci				if (err) {
11728c2ecf20Sopenharmony_ci					fprintf(stderr,
11738c2ecf20Sopenharmony_ci						"ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
11748c2ecf20Sopenharmony_ci						err, strerror(errno));
11758c2ecf20Sopenharmony_ci				}
11768c2ecf20Sopenharmony_ci			}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci			if (txmsg_ktls_skb_drop) {
11798c2ecf20Sopenharmony_ci				i = 1;
11808c2ecf20Sopenharmony_ci				err = bpf_map_update_elem(map_fd[7], &i, &i, BPF_ANY);
11818c2ecf20Sopenharmony_ci			}
11828c2ecf20Sopenharmony_ci		}
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci		if (txmsg_redir_skb) {
11858c2ecf20Sopenharmony_ci			int skb_fd = (test == SENDMSG || test == SENDPAGE) ?
11868c2ecf20Sopenharmony_ci					p2 : p1;
11878c2ecf20Sopenharmony_ci			int ingress = BPF_F_INGRESS;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci			i = 0;
11908c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[7],
11918c2ecf20Sopenharmony_ci						  &i, &ingress, BPF_ANY);
11928c2ecf20Sopenharmony_ci			if (err) {
11938c2ecf20Sopenharmony_ci				fprintf(stderr,
11948c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
11958c2ecf20Sopenharmony_ci					err, strerror(errno));
11968c2ecf20Sopenharmony_ci			}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci			i = 3;
11998c2ecf20Sopenharmony_ci			err = bpf_map_update_elem(map_fd[0], &i, &skb_fd, BPF_ANY);
12008c2ecf20Sopenharmony_ci			if (err) {
12018c2ecf20Sopenharmony_ci				fprintf(stderr,
12028c2ecf20Sopenharmony_ci					"ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
12038c2ecf20Sopenharmony_ci					err, strerror(errno));
12048c2ecf20Sopenharmony_ci			}
12058c2ecf20Sopenharmony_ci		}
12068c2ecf20Sopenharmony_ci	}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	if (skb_use_parser) {
12098c2ecf20Sopenharmony_ci		i = 2;
12108c2ecf20Sopenharmony_ci		err = bpf_map_update_elem(map_fd[7], &i, &skb_use_parser, BPF_ANY);
12118c2ecf20Sopenharmony_ci	}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	if (txmsg_drop)
12148c2ecf20Sopenharmony_ci		options->drop_expected = true;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	if (test == PING_PONG)
12178c2ecf20Sopenharmony_ci		err = forever_ping_pong(options->rate, options);
12188c2ecf20Sopenharmony_ci	else if (test == SENDMSG) {
12198c2ecf20Sopenharmony_ci		options->base = false;
12208c2ecf20Sopenharmony_ci		options->sendpage = false;
12218c2ecf20Sopenharmony_ci		err = sendmsg_test(options);
12228c2ecf20Sopenharmony_ci	} else if (test == SENDPAGE) {
12238c2ecf20Sopenharmony_ci		options->base = false;
12248c2ecf20Sopenharmony_ci		options->sendpage = true;
12258c2ecf20Sopenharmony_ci		err = sendmsg_test(options);
12268c2ecf20Sopenharmony_ci	} else if (test == BASE) {
12278c2ecf20Sopenharmony_ci		options->base = true;
12288c2ecf20Sopenharmony_ci		options->sendpage = false;
12298c2ecf20Sopenharmony_ci		err = sendmsg_test(options);
12308c2ecf20Sopenharmony_ci	} else if (test == BASE_SENDPAGE) {
12318c2ecf20Sopenharmony_ci		options->base = true;
12328c2ecf20Sopenharmony_ci		options->sendpage = true;
12338c2ecf20Sopenharmony_ci		err = sendmsg_test(options);
12348c2ecf20Sopenharmony_ci	} else
12358c2ecf20Sopenharmony_ci		fprintf(stderr, "unknown test\n");
12368c2ecf20Sopenharmony_ciout:
12378c2ecf20Sopenharmony_ci	/* Detatch and zero all the maps */
12388c2ecf20Sopenharmony_ci	bpf_prog_detach2(prog_fd[3], cg_fd, BPF_CGROUP_SOCK_OPS);
12398c2ecf20Sopenharmony_ci	bpf_prog_detach2(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER);
12408c2ecf20Sopenharmony_ci	bpf_prog_detach2(prog_fd[1], map_fd[0], BPF_SK_SKB_STREAM_VERDICT);
12418c2ecf20Sopenharmony_ci	bpf_prog_detach2(prog_fd[0], map_fd[8], BPF_SK_SKB_STREAM_PARSER);
12428c2ecf20Sopenharmony_ci	bpf_prog_detach2(prog_fd[2], map_fd[8], BPF_SK_SKB_STREAM_VERDICT);
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	if (tx_prog_fd >= 0)
12458c2ecf20Sopenharmony_ci		bpf_prog_detach2(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT);
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++) {
12488c2ecf20Sopenharmony_ci		key = next_key = 0;
12498c2ecf20Sopenharmony_ci		bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
12508c2ecf20Sopenharmony_ci		while (bpf_map_get_next_key(map_fd[i], &key, &next_key) == 0) {
12518c2ecf20Sopenharmony_ci			bpf_map_update_elem(map_fd[i], &key, &zero, BPF_ANY);
12528c2ecf20Sopenharmony_ci			key = next_key;
12538c2ecf20Sopenharmony_ci		}
12548c2ecf20Sopenharmony_ci	}
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	close(s1);
12578c2ecf20Sopenharmony_ci	close(s2);
12588c2ecf20Sopenharmony_ci	close(p1);
12598c2ecf20Sopenharmony_ci	close(p2);
12608c2ecf20Sopenharmony_ci	close(c1);
12618c2ecf20Sopenharmony_ci	close(c2);
12628c2ecf20Sopenharmony_ci	return err;
12638c2ecf20Sopenharmony_ci}
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_cistatic char *test_to_str(int test)
12668c2ecf20Sopenharmony_ci{
12678c2ecf20Sopenharmony_ci	switch (test) {
12688c2ecf20Sopenharmony_ci	case SENDMSG:
12698c2ecf20Sopenharmony_ci		return "sendmsg";
12708c2ecf20Sopenharmony_ci	case SENDPAGE:
12718c2ecf20Sopenharmony_ci		return "sendpage";
12728c2ecf20Sopenharmony_ci	}
12738c2ecf20Sopenharmony_ci	return "unknown";
12748c2ecf20Sopenharmony_ci}
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_cistatic void append_str(char *dst, const char *src, size_t dst_cap)
12778c2ecf20Sopenharmony_ci{
12788c2ecf20Sopenharmony_ci	size_t avail = dst_cap - strlen(dst);
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	if (avail <= 1) /* just zero byte could be written */
12818c2ecf20Sopenharmony_ci		return;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	strncat(dst, src, avail - 1); /* strncat() adds + 1 for zero byte */
12848c2ecf20Sopenharmony_ci}
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci#define OPTSTRING 60
12878c2ecf20Sopenharmony_cistatic void test_options(char *options)
12888c2ecf20Sopenharmony_ci{
12898c2ecf20Sopenharmony_ci	char tstr[OPTSTRING];
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	memset(options, 0, OPTSTRING);
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	if (txmsg_pass)
12948c2ecf20Sopenharmony_ci		append_str(options, "pass,", OPTSTRING);
12958c2ecf20Sopenharmony_ci	if (txmsg_redir)
12968c2ecf20Sopenharmony_ci		append_str(options, "redir,", OPTSTRING);
12978c2ecf20Sopenharmony_ci	if (txmsg_drop)
12988c2ecf20Sopenharmony_ci		append_str(options, "drop,", OPTSTRING);
12998c2ecf20Sopenharmony_ci	if (txmsg_apply) {
13008c2ecf20Sopenharmony_ci		snprintf(tstr, OPTSTRING, "apply %d,", txmsg_apply);
13018c2ecf20Sopenharmony_ci		append_str(options, tstr, OPTSTRING);
13028c2ecf20Sopenharmony_ci	}
13038c2ecf20Sopenharmony_ci	if (txmsg_cork) {
13048c2ecf20Sopenharmony_ci		snprintf(tstr, OPTSTRING, "cork %d,", txmsg_cork);
13058c2ecf20Sopenharmony_ci		append_str(options, tstr, OPTSTRING);
13068c2ecf20Sopenharmony_ci	}
13078c2ecf20Sopenharmony_ci	if (txmsg_start) {
13088c2ecf20Sopenharmony_ci		snprintf(tstr, OPTSTRING, "start %d,", txmsg_start);
13098c2ecf20Sopenharmony_ci		append_str(options, tstr, OPTSTRING);
13108c2ecf20Sopenharmony_ci	}
13118c2ecf20Sopenharmony_ci	if (txmsg_end) {
13128c2ecf20Sopenharmony_ci		snprintf(tstr, OPTSTRING, "end %d,", txmsg_end);
13138c2ecf20Sopenharmony_ci		append_str(options, tstr, OPTSTRING);
13148c2ecf20Sopenharmony_ci	}
13158c2ecf20Sopenharmony_ci	if (txmsg_start_pop) {
13168c2ecf20Sopenharmony_ci		snprintf(tstr, OPTSTRING, "pop (%d,%d),",
13178c2ecf20Sopenharmony_ci			 txmsg_start_pop, txmsg_start_pop + txmsg_pop);
13188c2ecf20Sopenharmony_ci		append_str(options, tstr, OPTSTRING);
13198c2ecf20Sopenharmony_ci	}
13208c2ecf20Sopenharmony_ci	if (txmsg_ingress)
13218c2ecf20Sopenharmony_ci		append_str(options, "ingress,", OPTSTRING);
13228c2ecf20Sopenharmony_ci	if (txmsg_redir_skb)
13238c2ecf20Sopenharmony_ci		append_str(options, "redir_skb,", OPTSTRING);
13248c2ecf20Sopenharmony_ci	if (txmsg_ktls_skb)
13258c2ecf20Sopenharmony_ci		append_str(options, "ktls_skb,", OPTSTRING);
13268c2ecf20Sopenharmony_ci	if (ktls)
13278c2ecf20Sopenharmony_ci		append_str(options, "ktls,", OPTSTRING);
13288c2ecf20Sopenharmony_ci	if (peek_flag)
13298c2ecf20Sopenharmony_ci		append_str(options, "peek,", OPTSTRING);
13308c2ecf20Sopenharmony_ci}
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_cistatic int __test_exec(int cgrp, int test, struct sockmap_options *opt)
13338c2ecf20Sopenharmony_ci{
13348c2ecf20Sopenharmony_ci	char *options = calloc(OPTSTRING, sizeof(char));
13358c2ecf20Sopenharmony_ci	int err;
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	if (test == SENDPAGE)
13388c2ecf20Sopenharmony_ci		opt->sendpage = true;
13398c2ecf20Sopenharmony_ci	else
13408c2ecf20Sopenharmony_ci		opt->sendpage = false;
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	if (txmsg_drop)
13438c2ecf20Sopenharmony_ci		opt->drop_expected = true;
13448c2ecf20Sopenharmony_ci	else
13458c2ecf20Sopenharmony_ci		opt->drop_expected = false;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	test_options(options);
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ci	if (opt->verbose) {
13508c2ecf20Sopenharmony_ci		fprintf(stdout,
13518c2ecf20Sopenharmony_ci			" [TEST %i]: (%i, %i, %i, %s, %s): ",
13528c2ecf20Sopenharmony_ci			test_cnt, opt->rate, opt->iov_count, opt->iov_length,
13538c2ecf20Sopenharmony_ci			test_to_str(test), options);
13548c2ecf20Sopenharmony_ci		fflush(stdout);
13558c2ecf20Sopenharmony_ci	}
13568c2ecf20Sopenharmony_ci	err = run_options(opt, cgrp, test);
13578c2ecf20Sopenharmony_ci	if (opt->verbose)
13588c2ecf20Sopenharmony_ci		fprintf(stdout, " %s\n", !err ? "PASS" : "FAILED");
13598c2ecf20Sopenharmony_ci	test_cnt++;
13608c2ecf20Sopenharmony_ci	!err ? passed++ : failed++;
13618c2ecf20Sopenharmony_ci	free(options);
13628c2ecf20Sopenharmony_ci	return err;
13638c2ecf20Sopenharmony_ci}
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_cistatic void test_exec(int cgrp, struct sockmap_options *opt)
13668c2ecf20Sopenharmony_ci{
13678c2ecf20Sopenharmony_ci	int type = strcmp(opt->map, BPF_SOCKMAP_FILENAME);
13688c2ecf20Sopenharmony_ci	int err;
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	if (type == 0) {
13718c2ecf20Sopenharmony_ci		test_start();
13728c2ecf20Sopenharmony_ci		err = __test_exec(cgrp, SENDMSG, opt);
13738c2ecf20Sopenharmony_ci		if (err)
13748c2ecf20Sopenharmony_ci			test_fail();
13758c2ecf20Sopenharmony_ci	} else {
13768c2ecf20Sopenharmony_ci		test_start();
13778c2ecf20Sopenharmony_ci		err = __test_exec(cgrp, SENDPAGE, opt);
13788c2ecf20Sopenharmony_ci		if (err)
13798c2ecf20Sopenharmony_ci			test_fail();
13808c2ecf20Sopenharmony_ci	}
13818c2ecf20Sopenharmony_ci}
13828c2ecf20Sopenharmony_ci
13838c2ecf20Sopenharmony_cistatic void test_send_one(struct sockmap_options *opt, int cgrp)
13848c2ecf20Sopenharmony_ci{
13858c2ecf20Sopenharmony_ci	opt->iov_length = 1;
13868c2ecf20Sopenharmony_ci	opt->iov_count = 1;
13878c2ecf20Sopenharmony_ci	opt->rate = 1;
13888c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
13898c2ecf20Sopenharmony_ci
13908c2ecf20Sopenharmony_ci	opt->iov_length = 1;
13918c2ecf20Sopenharmony_ci	opt->iov_count = 1024;
13928c2ecf20Sopenharmony_ci	opt->rate = 1;
13938c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	opt->iov_length = 1024;
13968c2ecf20Sopenharmony_ci	opt->iov_count = 1;
13978c2ecf20Sopenharmony_ci	opt->rate = 1;
13988c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci}
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_cistatic void test_send_many(struct sockmap_options *opt, int cgrp)
14038c2ecf20Sopenharmony_ci{
14048c2ecf20Sopenharmony_ci	opt->iov_length = 3;
14058c2ecf20Sopenharmony_ci	opt->iov_count = 1;
14068c2ecf20Sopenharmony_ci	opt->rate = 512;
14078c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	opt->rate = 100;
14108c2ecf20Sopenharmony_ci	opt->iov_count = 1;
14118c2ecf20Sopenharmony_ci	opt->iov_length = 5;
14128c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14138c2ecf20Sopenharmony_ci}
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_cistatic void test_send_large(struct sockmap_options *opt, int cgrp)
14168c2ecf20Sopenharmony_ci{
14178c2ecf20Sopenharmony_ci	opt->iov_length = 256;
14188c2ecf20Sopenharmony_ci	opt->iov_count = 1024;
14198c2ecf20Sopenharmony_ci	opt->rate = 2;
14208c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14218c2ecf20Sopenharmony_ci}
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_cistatic void test_send(struct sockmap_options *opt, int cgrp)
14248c2ecf20Sopenharmony_ci{
14258c2ecf20Sopenharmony_ci	test_send_one(opt, cgrp);
14268c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
14278c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
14288c2ecf20Sopenharmony_ci	sched_yield();
14298c2ecf20Sopenharmony_ci}
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_cistatic void test_txmsg_pass(int cgrp, struct sockmap_options *opt)
14328c2ecf20Sopenharmony_ci{
14338c2ecf20Sopenharmony_ci	/* Test small and large iov_count values with pass/redir/apply/cork */
14348c2ecf20Sopenharmony_ci	txmsg_pass = 1;
14358c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
14368c2ecf20Sopenharmony_ci}
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_cistatic void test_txmsg_redir(int cgrp, struct sockmap_options *opt)
14398c2ecf20Sopenharmony_ci{
14408c2ecf20Sopenharmony_ci	txmsg_redir = 1;
14418c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
14428c2ecf20Sopenharmony_ci}
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_cistatic void test_txmsg_drop(int cgrp, struct sockmap_options *opt)
14458c2ecf20Sopenharmony_ci{
14468c2ecf20Sopenharmony_ci	txmsg_drop = 1;
14478c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
14488c2ecf20Sopenharmony_ci}
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_cistatic void test_txmsg_ingress_redir(int cgrp, struct sockmap_options *opt)
14518c2ecf20Sopenharmony_ci{
14528c2ecf20Sopenharmony_ci	txmsg_pass = txmsg_drop = 0;
14538c2ecf20Sopenharmony_ci	txmsg_ingress = txmsg_redir = 1;
14548c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
14558c2ecf20Sopenharmony_ci}
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_cistatic void test_txmsg_skb(int cgrp, struct sockmap_options *opt)
14588c2ecf20Sopenharmony_ci{
14598c2ecf20Sopenharmony_ci	bool data = opt->data_test;
14608c2ecf20Sopenharmony_ci	int k = ktls;
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci	opt->data_test = true;
14638c2ecf20Sopenharmony_ci	ktls = 1;
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci	txmsg_pass = txmsg_drop = 0;
14668c2ecf20Sopenharmony_ci	txmsg_ingress = txmsg_redir = 0;
14678c2ecf20Sopenharmony_ci	txmsg_ktls_skb = 1;
14688c2ecf20Sopenharmony_ci	txmsg_pass = 1;
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	/* Using data verification so ensure iov layout is
14718c2ecf20Sopenharmony_ci	 * expected from test receiver side. e.g. has enough
14728c2ecf20Sopenharmony_ci	 * bytes to write test code.
14738c2ecf20Sopenharmony_ci	 */
14748c2ecf20Sopenharmony_ci	opt->iov_length = 100;
14758c2ecf20Sopenharmony_ci	opt->iov_count = 1;
14768c2ecf20Sopenharmony_ci	opt->rate = 1;
14778c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	txmsg_ktls_skb_drop = 1;
14808c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	txmsg_ktls_skb_drop = 0;
14838c2ecf20Sopenharmony_ci	txmsg_ktls_skb_redir = 1;
14848c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14858c2ecf20Sopenharmony_ci	txmsg_ktls_skb_redir = 0;
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	/* Tests that omit skb_parser */
14888c2ecf20Sopenharmony_ci	txmsg_omit_skb_parser = 1;
14898c2ecf20Sopenharmony_ci	ktls = 0;
14908c2ecf20Sopenharmony_ci	txmsg_ktls_skb = 0;
14918c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci	txmsg_ktls_skb_drop = 1;
14948c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14958c2ecf20Sopenharmony_ci	txmsg_ktls_skb_drop = 0;
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci	txmsg_ktls_skb_redir = 1;
14988c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	ktls = 1;
15018c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
15028c2ecf20Sopenharmony_ci	txmsg_omit_skb_parser = 0;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	opt->data_test = data;
15058c2ecf20Sopenharmony_ci	ktls = k;
15068c2ecf20Sopenharmony_ci}
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci/* Test cork with hung data. This tests poor usage patterns where
15098c2ecf20Sopenharmony_ci * cork can leave data on the ring if user program is buggy and
15108c2ecf20Sopenharmony_ci * doesn't flush them somehow. They do take some time however
15118c2ecf20Sopenharmony_ci * because they wait for a timeout. Test pass, redir and cork with
15128c2ecf20Sopenharmony_ci * apply logic. Use cork size of 4097 with send_large to avoid
15138c2ecf20Sopenharmony_ci * aligning cork size with send size.
15148c2ecf20Sopenharmony_ci */
15158c2ecf20Sopenharmony_cistatic void test_txmsg_cork_hangs(int cgrp, struct sockmap_options *opt)
15168c2ecf20Sopenharmony_ci{
15178c2ecf20Sopenharmony_ci	txmsg_pass = 1;
15188c2ecf20Sopenharmony_ci	txmsg_redir = 0;
15198c2ecf20Sopenharmony_ci	txmsg_cork = 4097;
15208c2ecf20Sopenharmony_ci	txmsg_apply = 4097;
15218c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	txmsg_pass = 0;
15248c2ecf20Sopenharmony_ci	txmsg_redir = 1;
15258c2ecf20Sopenharmony_ci	txmsg_apply = 0;
15268c2ecf20Sopenharmony_ci	txmsg_cork = 4097;
15278c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
15288c2ecf20Sopenharmony_ci
15298c2ecf20Sopenharmony_ci	txmsg_pass = 0;
15308c2ecf20Sopenharmony_ci	txmsg_redir = 1;
15318c2ecf20Sopenharmony_ci	txmsg_apply = 4097;
15328c2ecf20Sopenharmony_ci	txmsg_cork = 4097;
15338c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
15348c2ecf20Sopenharmony_ci}
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_cistatic void test_txmsg_pull(int cgrp, struct sockmap_options *opt)
15378c2ecf20Sopenharmony_ci{
15388c2ecf20Sopenharmony_ci	/* Test basic start/end */
15398c2ecf20Sopenharmony_ci	txmsg_start = 1;
15408c2ecf20Sopenharmony_ci	txmsg_end = 2;
15418c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	/* Test >4k pull */
15448c2ecf20Sopenharmony_ci	txmsg_start = 4096;
15458c2ecf20Sopenharmony_ci	txmsg_end = 9182;
15468c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	/* Test pull + redirect */
15498c2ecf20Sopenharmony_ci	txmsg_redir = 0;
15508c2ecf20Sopenharmony_ci	txmsg_start = 1;
15518c2ecf20Sopenharmony_ci	txmsg_end = 2;
15528c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	/* Test pull + cork */
15558c2ecf20Sopenharmony_ci	txmsg_redir = 0;
15568c2ecf20Sopenharmony_ci	txmsg_cork = 512;
15578c2ecf20Sopenharmony_ci	txmsg_start = 1;
15588c2ecf20Sopenharmony_ci	txmsg_end = 2;
15598c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	/* Test pull + cork + redirect */
15628c2ecf20Sopenharmony_ci	txmsg_redir = 1;
15638c2ecf20Sopenharmony_ci	txmsg_cork = 512;
15648c2ecf20Sopenharmony_ci	txmsg_start = 1;
15658c2ecf20Sopenharmony_ci	txmsg_end = 2;
15668c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
15678c2ecf20Sopenharmony_ci}
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_cistatic void test_txmsg_pop(int cgrp, struct sockmap_options *opt)
15708c2ecf20Sopenharmony_ci{
15718c2ecf20Sopenharmony_ci	/* Test basic pop */
15728c2ecf20Sopenharmony_ci	txmsg_start_pop = 1;
15738c2ecf20Sopenharmony_ci	txmsg_pop = 2;
15748c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	/* Test pop with >4k */
15778c2ecf20Sopenharmony_ci	txmsg_start_pop = 4096;
15788c2ecf20Sopenharmony_ci	txmsg_pop = 4096;
15798c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	/* Test pop + redirect */
15828c2ecf20Sopenharmony_ci	txmsg_redir = 1;
15838c2ecf20Sopenharmony_ci	txmsg_start_pop = 1;
15848c2ecf20Sopenharmony_ci	txmsg_pop = 2;
15858c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	/* Test pop + cork */
15888c2ecf20Sopenharmony_ci	txmsg_redir = 0;
15898c2ecf20Sopenharmony_ci	txmsg_cork = 512;
15908c2ecf20Sopenharmony_ci	txmsg_start_pop = 1;
15918c2ecf20Sopenharmony_ci	txmsg_pop = 2;
15928c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	/* Test pop + redirect + cork */
15958c2ecf20Sopenharmony_ci	txmsg_redir = 1;
15968c2ecf20Sopenharmony_ci	txmsg_cork = 4;
15978c2ecf20Sopenharmony_ci	txmsg_start_pop = 1;
15988c2ecf20Sopenharmony_ci	txmsg_pop = 2;
15998c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
16008c2ecf20Sopenharmony_ci}
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_cistatic void test_txmsg_push(int cgrp, struct sockmap_options *opt)
16038c2ecf20Sopenharmony_ci{
16048c2ecf20Sopenharmony_ci	/* Test basic push */
16058c2ecf20Sopenharmony_ci	txmsg_start_push = 1;
16068c2ecf20Sopenharmony_ci	txmsg_end_push = 1;
16078c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ci	/* Test push 4kB >4k */
16108c2ecf20Sopenharmony_ci	txmsg_start_push = 4096;
16118c2ecf20Sopenharmony_ci	txmsg_end_push = 4096;
16128c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	/* Test push + redirect */
16158c2ecf20Sopenharmony_ci	txmsg_redir = 1;
16168c2ecf20Sopenharmony_ci	txmsg_start_push = 1;
16178c2ecf20Sopenharmony_ci	txmsg_end_push = 2;
16188c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_ci	/* Test push + cork */
16218c2ecf20Sopenharmony_ci	txmsg_redir = 0;
16228c2ecf20Sopenharmony_ci	txmsg_cork = 512;
16238c2ecf20Sopenharmony_ci	txmsg_start_push = 1;
16248c2ecf20Sopenharmony_ci	txmsg_end_push = 2;
16258c2ecf20Sopenharmony_ci	test_send_many(opt, cgrp);
16268c2ecf20Sopenharmony_ci}
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_cistatic void test_txmsg_push_pop(int cgrp, struct sockmap_options *opt)
16298c2ecf20Sopenharmony_ci{
16308c2ecf20Sopenharmony_ci	txmsg_start_push = 1;
16318c2ecf20Sopenharmony_ci	txmsg_end_push = 10;
16328c2ecf20Sopenharmony_ci	txmsg_start_pop = 5;
16338c2ecf20Sopenharmony_ci	txmsg_pop = 4;
16348c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
16358c2ecf20Sopenharmony_ci}
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_cistatic void test_txmsg_apply(int cgrp, struct sockmap_options *opt)
16388c2ecf20Sopenharmony_ci{
16398c2ecf20Sopenharmony_ci	txmsg_pass = 1;
16408c2ecf20Sopenharmony_ci	txmsg_redir = 0;
16418c2ecf20Sopenharmony_ci	txmsg_apply = 1;
16428c2ecf20Sopenharmony_ci	txmsg_cork = 0;
16438c2ecf20Sopenharmony_ci	test_send_one(opt, cgrp);
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci	txmsg_pass = 0;
16468c2ecf20Sopenharmony_ci	txmsg_redir = 1;
16478c2ecf20Sopenharmony_ci	txmsg_apply = 1;
16488c2ecf20Sopenharmony_ci	txmsg_cork = 0;
16498c2ecf20Sopenharmony_ci	test_send_one(opt, cgrp);
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	txmsg_pass = 1;
16528c2ecf20Sopenharmony_ci	txmsg_redir = 0;
16538c2ecf20Sopenharmony_ci	txmsg_apply = 1024;
16548c2ecf20Sopenharmony_ci	txmsg_cork = 0;
16558c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	txmsg_pass = 0;
16588c2ecf20Sopenharmony_ci	txmsg_redir = 1;
16598c2ecf20Sopenharmony_ci	txmsg_apply = 1024;
16608c2ecf20Sopenharmony_ci	txmsg_cork = 0;
16618c2ecf20Sopenharmony_ci	test_send_large(opt, cgrp);
16628c2ecf20Sopenharmony_ci}
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_cistatic void test_txmsg_cork(int cgrp, struct sockmap_options *opt)
16658c2ecf20Sopenharmony_ci{
16668c2ecf20Sopenharmony_ci	txmsg_pass = 1;
16678c2ecf20Sopenharmony_ci	txmsg_redir = 0;
16688c2ecf20Sopenharmony_ci	txmsg_apply = 0;
16698c2ecf20Sopenharmony_ci	txmsg_cork = 1;
16708c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	txmsg_pass = 1;
16738c2ecf20Sopenharmony_ci	txmsg_redir = 0;
16748c2ecf20Sopenharmony_ci	txmsg_apply = 1;
16758c2ecf20Sopenharmony_ci	txmsg_cork = 1;
16768c2ecf20Sopenharmony_ci	test_send(opt, cgrp);
16778c2ecf20Sopenharmony_ci}
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_cistatic void test_txmsg_ingress_parser(int cgrp, struct sockmap_options *opt)
16808c2ecf20Sopenharmony_ci{
16818c2ecf20Sopenharmony_ci	txmsg_pass = 1;
16828c2ecf20Sopenharmony_ci	skb_use_parser = 512;
16838c2ecf20Sopenharmony_ci	opt->iov_length = 256;
16848c2ecf20Sopenharmony_ci	opt->iov_count = 1;
16858c2ecf20Sopenharmony_ci	opt->rate = 2;
16868c2ecf20Sopenharmony_ci	test_exec(cgrp, opt);
16878c2ecf20Sopenharmony_ci}
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_cichar *map_names[] = {
16908c2ecf20Sopenharmony_ci	"sock_map",
16918c2ecf20Sopenharmony_ci	"sock_map_txmsg",
16928c2ecf20Sopenharmony_ci	"sock_map_redir",
16938c2ecf20Sopenharmony_ci	"sock_apply_bytes",
16948c2ecf20Sopenharmony_ci	"sock_cork_bytes",
16958c2ecf20Sopenharmony_ci	"sock_bytes",
16968c2ecf20Sopenharmony_ci	"sock_redir_flags",
16978c2ecf20Sopenharmony_ci	"sock_skb_opts",
16988c2ecf20Sopenharmony_ci	"tls_sock_map",
16998c2ecf20Sopenharmony_ci};
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ciint prog_attach_type[] = {
17028c2ecf20Sopenharmony_ci	BPF_SK_SKB_STREAM_PARSER,
17038c2ecf20Sopenharmony_ci	BPF_SK_SKB_STREAM_VERDICT,
17048c2ecf20Sopenharmony_ci	BPF_SK_SKB_STREAM_VERDICT,
17058c2ecf20Sopenharmony_ci	BPF_CGROUP_SOCK_OPS,
17068c2ecf20Sopenharmony_ci	BPF_SK_MSG_VERDICT,
17078c2ecf20Sopenharmony_ci	BPF_SK_MSG_VERDICT,
17088c2ecf20Sopenharmony_ci	BPF_SK_MSG_VERDICT,
17098c2ecf20Sopenharmony_ci	BPF_SK_MSG_VERDICT,
17108c2ecf20Sopenharmony_ci	BPF_SK_MSG_VERDICT,
17118c2ecf20Sopenharmony_ci	BPF_SK_MSG_VERDICT,
17128c2ecf20Sopenharmony_ci	BPF_SK_MSG_VERDICT,
17138c2ecf20Sopenharmony_ci};
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ciint prog_type[] = {
17168c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_SKB,
17178c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_SKB,
17188c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_SKB,
17198c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SOCK_OPS,
17208c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_MSG,
17218c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_MSG,
17228c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_MSG,
17238c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_MSG,
17248c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_MSG,
17258c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_MSG,
17268c2ecf20Sopenharmony_ci	BPF_PROG_TYPE_SK_MSG,
17278c2ecf20Sopenharmony_ci};
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_cistatic int populate_progs(char *bpf_file)
17308c2ecf20Sopenharmony_ci{
17318c2ecf20Sopenharmony_ci	struct bpf_program *prog;
17328c2ecf20Sopenharmony_ci	struct bpf_object *obj;
17338c2ecf20Sopenharmony_ci	int i = 0;
17348c2ecf20Sopenharmony_ci	long err;
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_ci	obj = bpf_object__open(bpf_file);
17378c2ecf20Sopenharmony_ci	err = libbpf_get_error(obj);
17388c2ecf20Sopenharmony_ci	if (err) {
17398c2ecf20Sopenharmony_ci		char err_buf[256];
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci		libbpf_strerror(err, err_buf, sizeof(err_buf));
17428c2ecf20Sopenharmony_ci		printf("Unable to load eBPF objects in file '%s' : %s\n",
17438c2ecf20Sopenharmony_ci		       bpf_file, err_buf);
17448c2ecf20Sopenharmony_ci		return -1;
17458c2ecf20Sopenharmony_ci	}
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ci	bpf_object__for_each_program(prog, obj) {
17488c2ecf20Sopenharmony_ci		bpf_program__set_type(prog, prog_type[i]);
17498c2ecf20Sopenharmony_ci		bpf_program__set_expected_attach_type(prog,
17508c2ecf20Sopenharmony_ci						      prog_attach_type[i]);
17518c2ecf20Sopenharmony_ci		i++;
17528c2ecf20Sopenharmony_ci	}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci	i = bpf_object__load(obj);
17558c2ecf20Sopenharmony_ci	i = 0;
17568c2ecf20Sopenharmony_ci	bpf_object__for_each_program(prog, obj) {
17578c2ecf20Sopenharmony_ci		prog_fd[i] = bpf_program__fd(prog);
17588c2ecf20Sopenharmony_ci		i++;
17598c2ecf20Sopenharmony_ci	}
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof(map_fd)/sizeof(int); i++) {
17628c2ecf20Sopenharmony_ci		maps[i] = bpf_object__find_map_by_name(obj, map_names[i]);
17638c2ecf20Sopenharmony_ci		map_fd[i] = bpf_map__fd(maps[i]);
17648c2ecf20Sopenharmony_ci		if (map_fd[i] < 0) {
17658c2ecf20Sopenharmony_ci			fprintf(stderr, "load_bpf_file: (%i) %s\n",
17668c2ecf20Sopenharmony_ci				map_fd[i], strerror(errno));
17678c2ecf20Sopenharmony_ci			return -1;
17688c2ecf20Sopenharmony_ci		}
17698c2ecf20Sopenharmony_ci	}
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	return 0;
17728c2ecf20Sopenharmony_ci}
17738c2ecf20Sopenharmony_ci
17748c2ecf20Sopenharmony_cistruct _test test[] = {
17758c2ecf20Sopenharmony_ci	{"txmsg test passthrough", test_txmsg_pass},
17768c2ecf20Sopenharmony_ci	{"txmsg test redirect", test_txmsg_redir},
17778c2ecf20Sopenharmony_ci	{"txmsg test drop", test_txmsg_drop},
17788c2ecf20Sopenharmony_ci	{"txmsg test ingress redirect", test_txmsg_ingress_redir},
17798c2ecf20Sopenharmony_ci	{"txmsg test skb", test_txmsg_skb},
17808c2ecf20Sopenharmony_ci	{"txmsg test apply", test_txmsg_apply},
17818c2ecf20Sopenharmony_ci	{"txmsg test cork", test_txmsg_cork},
17828c2ecf20Sopenharmony_ci	{"txmsg test hanging corks", test_txmsg_cork_hangs},
17838c2ecf20Sopenharmony_ci	{"txmsg test push_data", test_txmsg_push},
17848c2ecf20Sopenharmony_ci	{"txmsg test pull-data", test_txmsg_pull},
17858c2ecf20Sopenharmony_ci	{"txmsg test pop-data", test_txmsg_pop},
17868c2ecf20Sopenharmony_ci	{"txmsg test push/pop data", test_txmsg_push_pop},
17878c2ecf20Sopenharmony_ci	{"txmsg text ingress parser", test_txmsg_ingress_parser},
17888c2ecf20Sopenharmony_ci};
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_cistatic int check_whitelist(struct _test *t, struct sockmap_options *opt)
17918c2ecf20Sopenharmony_ci{
17928c2ecf20Sopenharmony_ci	char *entry, *ptr;
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci	if (!opt->whitelist)
17958c2ecf20Sopenharmony_ci		return 0;
17968c2ecf20Sopenharmony_ci	ptr = strdup(opt->whitelist);
17978c2ecf20Sopenharmony_ci	if (!ptr)
17988c2ecf20Sopenharmony_ci		return -ENOMEM;
17998c2ecf20Sopenharmony_ci	entry = strtok(ptr, ",");
18008c2ecf20Sopenharmony_ci	while (entry) {
18018c2ecf20Sopenharmony_ci		if ((opt->prepend && strstr(opt->prepend, entry) != 0) ||
18028c2ecf20Sopenharmony_ci		    strstr(opt->map, entry) != 0 ||
18038c2ecf20Sopenharmony_ci		    strstr(t->title, entry) != 0)
18048c2ecf20Sopenharmony_ci			return 0;
18058c2ecf20Sopenharmony_ci		entry = strtok(NULL, ",");
18068c2ecf20Sopenharmony_ci	}
18078c2ecf20Sopenharmony_ci	return -EINVAL;
18088c2ecf20Sopenharmony_ci}
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_cistatic int check_blacklist(struct _test *t, struct sockmap_options *opt)
18118c2ecf20Sopenharmony_ci{
18128c2ecf20Sopenharmony_ci	char *entry, *ptr;
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci	if (!opt->blacklist)
18158c2ecf20Sopenharmony_ci		return -EINVAL;
18168c2ecf20Sopenharmony_ci	ptr = strdup(opt->blacklist);
18178c2ecf20Sopenharmony_ci	if (!ptr)
18188c2ecf20Sopenharmony_ci		return -ENOMEM;
18198c2ecf20Sopenharmony_ci	entry = strtok(ptr, ",");
18208c2ecf20Sopenharmony_ci	while (entry) {
18218c2ecf20Sopenharmony_ci		if ((opt->prepend && strstr(opt->prepend, entry) != 0) ||
18228c2ecf20Sopenharmony_ci		    strstr(opt->map, entry) != 0 ||
18238c2ecf20Sopenharmony_ci		    strstr(t->title, entry) != 0)
18248c2ecf20Sopenharmony_ci			return 0;
18258c2ecf20Sopenharmony_ci		entry = strtok(NULL, ",");
18268c2ecf20Sopenharmony_ci	}
18278c2ecf20Sopenharmony_ci	return -EINVAL;
18288c2ecf20Sopenharmony_ci}
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_cistatic int __test_selftests(int cg_fd, struct sockmap_options *opt)
18318c2ecf20Sopenharmony_ci{
18328c2ecf20Sopenharmony_ci	int i, err;
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci	err = populate_progs(opt->map);
18358c2ecf20Sopenharmony_ci	if (err < 0) {
18368c2ecf20Sopenharmony_ci		fprintf(stderr, "ERROR: (%i) load bpf failed\n", err);
18378c2ecf20Sopenharmony_ci		return err;
18388c2ecf20Sopenharmony_ci	}
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	/* Tests basic commands and APIs */
18418c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof(test)/sizeof(struct _test); i++) {
18428c2ecf20Sopenharmony_ci		struct _test t = test[i];
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci		if (check_whitelist(&t, opt) != 0)
18458c2ecf20Sopenharmony_ci			continue;
18468c2ecf20Sopenharmony_ci		if (check_blacklist(&t, opt) == 0)
18478c2ecf20Sopenharmony_ci			continue;
18488c2ecf20Sopenharmony_ci
18498c2ecf20Sopenharmony_ci		test_start_subtest(&t, opt);
18508c2ecf20Sopenharmony_ci		t.tester(cg_fd, opt);
18518c2ecf20Sopenharmony_ci		test_end_subtest();
18528c2ecf20Sopenharmony_ci	}
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_ci	return err;
18558c2ecf20Sopenharmony_ci}
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_cistatic void test_selftests_sockmap(int cg_fd, struct sockmap_options *opt)
18588c2ecf20Sopenharmony_ci{
18598c2ecf20Sopenharmony_ci	opt->map = BPF_SOCKMAP_FILENAME;
18608c2ecf20Sopenharmony_ci	__test_selftests(cg_fd, opt);
18618c2ecf20Sopenharmony_ci}
18628c2ecf20Sopenharmony_ci
18638c2ecf20Sopenharmony_cistatic void test_selftests_sockhash(int cg_fd, struct sockmap_options *opt)
18648c2ecf20Sopenharmony_ci{
18658c2ecf20Sopenharmony_ci	opt->map = BPF_SOCKHASH_FILENAME;
18668c2ecf20Sopenharmony_ci	__test_selftests(cg_fd, opt);
18678c2ecf20Sopenharmony_ci}
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_cistatic void test_selftests_ktls(int cg_fd, struct sockmap_options *opt)
18708c2ecf20Sopenharmony_ci{
18718c2ecf20Sopenharmony_ci	opt->map = BPF_SOCKHASH_FILENAME;
18728c2ecf20Sopenharmony_ci	opt->prepend = "ktls";
18738c2ecf20Sopenharmony_ci	ktls = 1;
18748c2ecf20Sopenharmony_ci	__test_selftests(cg_fd, opt);
18758c2ecf20Sopenharmony_ci	ktls = 0;
18768c2ecf20Sopenharmony_ci}
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_cistatic int test_selftest(int cg_fd, struct sockmap_options *opt)
18798c2ecf20Sopenharmony_ci{
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci	test_selftests_sockmap(cg_fd, opt);
18828c2ecf20Sopenharmony_ci	test_selftests_sockhash(cg_fd, opt);
18838c2ecf20Sopenharmony_ci	test_selftests_ktls(cg_fd, opt);
18848c2ecf20Sopenharmony_ci	test_print_results();
18858c2ecf20Sopenharmony_ci	return 0;
18868c2ecf20Sopenharmony_ci}
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_ciint main(int argc, char **argv)
18898c2ecf20Sopenharmony_ci{
18908c2ecf20Sopenharmony_ci	int iov_count = 1, length = 1024, rate = 1;
18918c2ecf20Sopenharmony_ci	struct sockmap_options options = {0};
18928c2ecf20Sopenharmony_ci	int opt, longindex, err, cg_fd = 0;
18938c2ecf20Sopenharmony_ci	char *bpf_file = BPF_SOCKMAP_FILENAME;
18948c2ecf20Sopenharmony_ci	int test = SELFTESTS;
18958c2ecf20Sopenharmony_ci	bool cg_created = 0;
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci	while ((opt = getopt_long(argc, argv, ":dhv:c:r:i:l:t:p:q:n:b:",
18988c2ecf20Sopenharmony_ci				  long_options, &longindex)) != -1) {
18998c2ecf20Sopenharmony_ci		switch (opt) {
19008c2ecf20Sopenharmony_ci		case 's':
19018c2ecf20Sopenharmony_ci			txmsg_start = atoi(optarg);
19028c2ecf20Sopenharmony_ci			break;
19038c2ecf20Sopenharmony_ci		case 'e':
19048c2ecf20Sopenharmony_ci			txmsg_end = atoi(optarg);
19058c2ecf20Sopenharmony_ci			break;
19068c2ecf20Sopenharmony_ci		case 'p':
19078c2ecf20Sopenharmony_ci			txmsg_start_push = atoi(optarg);
19088c2ecf20Sopenharmony_ci			break;
19098c2ecf20Sopenharmony_ci		case 'q':
19108c2ecf20Sopenharmony_ci			txmsg_end_push = atoi(optarg);
19118c2ecf20Sopenharmony_ci			break;
19128c2ecf20Sopenharmony_ci		case 'w':
19138c2ecf20Sopenharmony_ci			txmsg_start_pop = atoi(optarg);
19148c2ecf20Sopenharmony_ci			break;
19158c2ecf20Sopenharmony_ci		case 'x':
19168c2ecf20Sopenharmony_ci			txmsg_pop = atoi(optarg);
19178c2ecf20Sopenharmony_ci			break;
19188c2ecf20Sopenharmony_ci		case 'a':
19198c2ecf20Sopenharmony_ci			txmsg_apply = atoi(optarg);
19208c2ecf20Sopenharmony_ci			break;
19218c2ecf20Sopenharmony_ci		case 'k':
19228c2ecf20Sopenharmony_ci			txmsg_cork = atoi(optarg);
19238c2ecf20Sopenharmony_ci			break;
19248c2ecf20Sopenharmony_ci		case 'c':
19258c2ecf20Sopenharmony_ci			cg_fd = open(optarg, O_DIRECTORY, O_RDONLY);
19268c2ecf20Sopenharmony_ci			if (cg_fd < 0) {
19278c2ecf20Sopenharmony_ci				fprintf(stderr,
19288c2ecf20Sopenharmony_ci					"ERROR: (%i) open cg path failed: %s\n",
19298c2ecf20Sopenharmony_ci					cg_fd, optarg);
19308c2ecf20Sopenharmony_ci				return cg_fd;
19318c2ecf20Sopenharmony_ci			}
19328c2ecf20Sopenharmony_ci			break;
19338c2ecf20Sopenharmony_ci		case 'r':
19348c2ecf20Sopenharmony_ci			rate = atoi(optarg);
19358c2ecf20Sopenharmony_ci			break;
19368c2ecf20Sopenharmony_ci		case 'v':
19378c2ecf20Sopenharmony_ci			options.verbose = 1;
19388c2ecf20Sopenharmony_ci			if (optarg)
19398c2ecf20Sopenharmony_ci				options.verbose = atoi(optarg);
19408c2ecf20Sopenharmony_ci			break;
19418c2ecf20Sopenharmony_ci		case 'i':
19428c2ecf20Sopenharmony_ci			iov_count = atoi(optarg);
19438c2ecf20Sopenharmony_ci			break;
19448c2ecf20Sopenharmony_ci		case 'l':
19458c2ecf20Sopenharmony_ci			length = atoi(optarg);
19468c2ecf20Sopenharmony_ci			break;
19478c2ecf20Sopenharmony_ci		case 'd':
19488c2ecf20Sopenharmony_ci			options.data_test = true;
19498c2ecf20Sopenharmony_ci			break;
19508c2ecf20Sopenharmony_ci		case 't':
19518c2ecf20Sopenharmony_ci			if (strcmp(optarg, "ping") == 0) {
19528c2ecf20Sopenharmony_ci				test = PING_PONG;
19538c2ecf20Sopenharmony_ci			} else if (strcmp(optarg, "sendmsg") == 0) {
19548c2ecf20Sopenharmony_ci				test = SENDMSG;
19558c2ecf20Sopenharmony_ci			} else if (strcmp(optarg, "base") == 0) {
19568c2ecf20Sopenharmony_ci				test = BASE;
19578c2ecf20Sopenharmony_ci			} else if (strcmp(optarg, "base_sendpage") == 0) {
19588c2ecf20Sopenharmony_ci				test = BASE_SENDPAGE;
19598c2ecf20Sopenharmony_ci			} else if (strcmp(optarg, "sendpage") == 0) {
19608c2ecf20Sopenharmony_ci				test = SENDPAGE;
19618c2ecf20Sopenharmony_ci			} else {
19628c2ecf20Sopenharmony_ci				usage(argv);
19638c2ecf20Sopenharmony_ci				return -1;
19648c2ecf20Sopenharmony_ci			}
19658c2ecf20Sopenharmony_ci			break;
19668c2ecf20Sopenharmony_ci		case 'n':
19678c2ecf20Sopenharmony_ci			options.whitelist = strdup(optarg);
19688c2ecf20Sopenharmony_ci			if (!options.whitelist)
19698c2ecf20Sopenharmony_ci				return -ENOMEM;
19708c2ecf20Sopenharmony_ci			break;
19718c2ecf20Sopenharmony_ci		case 'b':
19728c2ecf20Sopenharmony_ci			options.blacklist = strdup(optarg);
19738c2ecf20Sopenharmony_ci			if (!options.blacklist)
19748c2ecf20Sopenharmony_ci				return -ENOMEM;
19758c2ecf20Sopenharmony_ci		case 0:
19768c2ecf20Sopenharmony_ci			break;
19778c2ecf20Sopenharmony_ci		case 'h':
19788c2ecf20Sopenharmony_ci		default:
19798c2ecf20Sopenharmony_ci			usage(argv);
19808c2ecf20Sopenharmony_ci			return -1;
19818c2ecf20Sopenharmony_ci		}
19828c2ecf20Sopenharmony_ci	}
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	if (!cg_fd) {
19858c2ecf20Sopenharmony_ci		cg_fd = cgroup_setup_and_join(CG_PATH);
19868c2ecf20Sopenharmony_ci		if (cg_fd < 0)
19878c2ecf20Sopenharmony_ci			return cg_fd;
19888c2ecf20Sopenharmony_ci		cg_created = 1;
19898c2ecf20Sopenharmony_ci	}
19908c2ecf20Sopenharmony_ci
19918c2ecf20Sopenharmony_ci	if (test == SELFTESTS) {
19928c2ecf20Sopenharmony_ci		err = test_selftest(cg_fd, &options);
19938c2ecf20Sopenharmony_ci		goto out;
19948c2ecf20Sopenharmony_ci	}
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_ci	err = populate_progs(bpf_file);
19978c2ecf20Sopenharmony_ci	if (err) {
19988c2ecf20Sopenharmony_ci		fprintf(stderr, "populate program: (%s) %s\n",
19998c2ecf20Sopenharmony_ci			bpf_file, strerror(errno));
20008c2ecf20Sopenharmony_ci		return 1;
20018c2ecf20Sopenharmony_ci	}
20028c2ecf20Sopenharmony_ci	running = 1;
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci	/* catch SIGINT */
20058c2ecf20Sopenharmony_ci	signal(SIGINT, running_handler);
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	options.iov_count = iov_count;
20088c2ecf20Sopenharmony_ci	options.iov_length = length;
20098c2ecf20Sopenharmony_ci	options.rate = rate;
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_ci	err = run_options(&options, cg_fd, test);
20128c2ecf20Sopenharmony_ciout:
20138c2ecf20Sopenharmony_ci	if (options.whitelist)
20148c2ecf20Sopenharmony_ci		free(options.whitelist);
20158c2ecf20Sopenharmony_ci	if (options.blacklist)
20168c2ecf20Sopenharmony_ci		free(options.blacklist);
20178c2ecf20Sopenharmony_ci	if (cg_created)
20188c2ecf20Sopenharmony_ci		cleanup_cgroup_environment();
20198c2ecf20Sopenharmony_ci	close(cg_fd);
20208c2ecf20Sopenharmony_ci	return err;
20218c2ecf20Sopenharmony_ci}
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_civoid running_handler(int a)
20248c2ecf20Sopenharmony_ci{
20258c2ecf20Sopenharmony_ci	running = 0;
20268c2ecf20Sopenharmony_ci}
2027