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