18c2ecf20Sopenharmony_ci#include <linux/unistd.h> 28c2ecf20Sopenharmony_ci#include <linux/bpf.h> 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <stdio.h> 58c2ecf20Sopenharmony_ci#include <stdlib.h> 68c2ecf20Sopenharmony_ci#include <stdint.h> 78c2ecf20Sopenharmony_ci#include <unistd.h> 88c2ecf20Sopenharmony_ci#include <string.h> 98c2ecf20Sopenharmony_ci#include <assert.h> 108c2ecf20Sopenharmony_ci#include <errno.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <sys/types.h> 138c2ecf20Sopenharmony_ci#include <sys/socket.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <bpf/libbpf.h> 188c2ecf20Sopenharmony_ci#include "bpf_insn.h" 198c2ecf20Sopenharmony_ci#include "sock_example.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define BPF_F_PIN (1 << 0) 228c2ecf20Sopenharmony_ci#define BPF_F_GET (1 << 1) 238c2ecf20Sopenharmony_ci#define BPF_F_PIN_GET (BPF_F_PIN | BPF_F_GET) 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define BPF_F_KEY (1 << 2) 268c2ecf20Sopenharmony_ci#define BPF_F_VAL (1 << 3) 278c2ecf20Sopenharmony_ci#define BPF_F_KEY_VAL (BPF_F_KEY | BPF_F_VAL) 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define BPF_M_UNSPEC 0 308c2ecf20Sopenharmony_ci#define BPF_M_MAP 1 318c2ecf20Sopenharmony_ci#define BPF_M_PROG 2 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cichar bpf_log_buf[BPF_LOG_BUF_SIZE]; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic void usage(void) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci printf("Usage: fds_example [...]\n"); 388c2ecf20Sopenharmony_ci printf(" -F <file> File to pin/get object\n"); 398c2ecf20Sopenharmony_ci printf(" -P |- pin object\n"); 408c2ecf20Sopenharmony_ci printf(" -G `- get object\n"); 418c2ecf20Sopenharmony_ci printf(" -m eBPF map mode\n"); 428c2ecf20Sopenharmony_ci printf(" -k <key> |- map key\n"); 438c2ecf20Sopenharmony_ci printf(" -v <value> `- map value\n"); 448c2ecf20Sopenharmony_ci printf(" -p eBPF prog mode\n"); 458c2ecf20Sopenharmony_ci printf(" -o <object> `- object file\n"); 468c2ecf20Sopenharmony_ci printf(" -h Display this help.\n"); 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic int bpf_map_create(void) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci return bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(uint32_t), 528c2ecf20Sopenharmony_ci sizeof(uint32_t), 1024, 0); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic int bpf_prog_create(const char *object) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci static struct bpf_insn insns[] = { 588c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 1), 598c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 608c2ecf20Sopenharmony_ci }; 618c2ecf20Sopenharmony_ci size_t insns_cnt = sizeof(insns) / sizeof(struct bpf_insn); 628c2ecf20Sopenharmony_ci struct bpf_object *obj; 638c2ecf20Sopenharmony_ci int prog_fd; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if (object) { 668c2ecf20Sopenharmony_ci assert(!bpf_prog_load(object, BPF_PROG_TYPE_UNSPEC, 678c2ecf20Sopenharmony_ci &obj, &prog_fd)); 688c2ecf20Sopenharmony_ci return prog_fd; 698c2ecf20Sopenharmony_ci } else { 708c2ecf20Sopenharmony_ci return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, 718c2ecf20Sopenharmony_ci insns, insns_cnt, "GPL", 0, 728c2ecf20Sopenharmony_ci bpf_log_buf, BPF_LOG_BUF_SIZE); 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic int bpf_do_map(const char *file, uint32_t flags, uint32_t key, 778c2ecf20Sopenharmony_ci uint32_t value) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci int fd, ret; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (flags & BPF_F_PIN) { 828c2ecf20Sopenharmony_ci fd = bpf_map_create(); 838c2ecf20Sopenharmony_ci printf("bpf: map fd:%d (%s)\n", fd, strerror(errno)); 848c2ecf20Sopenharmony_ci assert(fd > 0); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci ret = bpf_obj_pin(fd, file); 878c2ecf20Sopenharmony_ci printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 888c2ecf20Sopenharmony_ci assert(ret == 0); 898c2ecf20Sopenharmony_ci } else { 908c2ecf20Sopenharmony_ci fd = bpf_obj_get(file); 918c2ecf20Sopenharmony_ci printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 928c2ecf20Sopenharmony_ci assert(fd > 0); 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) { 968c2ecf20Sopenharmony_ci ret = bpf_map_update_elem(fd, &key, &value, 0); 978c2ecf20Sopenharmony_ci printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value, 988c2ecf20Sopenharmony_ci ret, strerror(errno)); 998c2ecf20Sopenharmony_ci assert(ret == 0); 1008c2ecf20Sopenharmony_ci } else if (flags & BPF_F_KEY) { 1018c2ecf20Sopenharmony_ci ret = bpf_map_lookup_elem(fd, &key, &value); 1028c2ecf20Sopenharmony_ci printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value, 1038c2ecf20Sopenharmony_ci ret, strerror(errno)); 1048c2ecf20Sopenharmony_ci assert(ret == 0); 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci return 0; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic int bpf_do_prog(const char *file, uint32_t flags, const char *object) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci int fd, sock, ret; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (flags & BPF_F_PIN) { 1158c2ecf20Sopenharmony_ci fd = bpf_prog_create(object); 1168c2ecf20Sopenharmony_ci printf("bpf: prog fd:%d (%s)\n", fd, strerror(errno)); 1178c2ecf20Sopenharmony_ci assert(fd > 0); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci ret = bpf_obj_pin(fd, file); 1208c2ecf20Sopenharmony_ci printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 1218c2ecf20Sopenharmony_ci assert(ret == 0); 1228c2ecf20Sopenharmony_ci } else { 1238c2ecf20Sopenharmony_ci fd = bpf_obj_get(file); 1248c2ecf20Sopenharmony_ci printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 1258c2ecf20Sopenharmony_ci assert(fd > 0); 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci sock = open_raw_sock("lo"); 1298c2ecf20Sopenharmony_ci assert(sock > 0); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &fd, sizeof(fd)); 1328c2ecf20Sopenharmony_ci printf("bpf: sock:%d <- fd:%d attached ret:(%d,%s)\n", sock, fd, 1338c2ecf20Sopenharmony_ci ret, strerror(errno)); 1348c2ecf20Sopenharmony_ci assert(ret == 0); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci return 0; 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ciint main(int argc, char **argv) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci const char *file = NULL, *object = NULL; 1428c2ecf20Sopenharmony_ci uint32_t key = 0, value = 0, flags = 0; 1438c2ecf20Sopenharmony_ci int opt, mode = BPF_M_UNSPEC; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci while ((opt = getopt(argc, argv, "F:PGmk:v:po:")) != -1) { 1468c2ecf20Sopenharmony_ci switch (opt) { 1478c2ecf20Sopenharmony_ci /* General args */ 1488c2ecf20Sopenharmony_ci case 'F': 1498c2ecf20Sopenharmony_ci file = optarg; 1508c2ecf20Sopenharmony_ci break; 1518c2ecf20Sopenharmony_ci case 'P': 1528c2ecf20Sopenharmony_ci flags |= BPF_F_PIN; 1538c2ecf20Sopenharmony_ci break; 1548c2ecf20Sopenharmony_ci case 'G': 1558c2ecf20Sopenharmony_ci flags |= BPF_F_GET; 1568c2ecf20Sopenharmony_ci break; 1578c2ecf20Sopenharmony_ci /* Map-related args */ 1588c2ecf20Sopenharmony_ci case 'm': 1598c2ecf20Sopenharmony_ci mode = BPF_M_MAP; 1608c2ecf20Sopenharmony_ci break; 1618c2ecf20Sopenharmony_ci case 'k': 1628c2ecf20Sopenharmony_ci key = strtoul(optarg, NULL, 0); 1638c2ecf20Sopenharmony_ci flags |= BPF_F_KEY; 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci case 'v': 1668c2ecf20Sopenharmony_ci value = strtoul(optarg, NULL, 0); 1678c2ecf20Sopenharmony_ci flags |= BPF_F_VAL; 1688c2ecf20Sopenharmony_ci break; 1698c2ecf20Sopenharmony_ci /* Prog-related args */ 1708c2ecf20Sopenharmony_ci case 'p': 1718c2ecf20Sopenharmony_ci mode = BPF_M_PROG; 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci case 'o': 1748c2ecf20Sopenharmony_ci object = optarg; 1758c2ecf20Sopenharmony_ci break; 1768c2ecf20Sopenharmony_ci default: 1778c2ecf20Sopenharmony_ci goto out; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci if (!(flags & BPF_F_PIN_GET) || !file) 1828c2ecf20Sopenharmony_ci goto out; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci switch (mode) { 1858c2ecf20Sopenharmony_ci case BPF_M_MAP: 1868c2ecf20Sopenharmony_ci return bpf_do_map(file, flags, key, value); 1878c2ecf20Sopenharmony_ci case BPF_M_PROG: 1888c2ecf20Sopenharmony_ci return bpf_do_prog(file, flags, object); 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ciout: 1918c2ecf20Sopenharmony_ci usage(); 1928c2ecf20Sopenharmony_ci return -1; 1938c2ecf20Sopenharmony_ci} 194