162306a36Sopenharmony_ci#include <linux/unistd.h> 262306a36Sopenharmony_ci#include <linux/bpf.h> 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <stdio.h> 562306a36Sopenharmony_ci#include <stdlib.h> 662306a36Sopenharmony_ci#include <stdint.h> 762306a36Sopenharmony_ci#include <unistd.h> 862306a36Sopenharmony_ci#include <string.h> 962306a36Sopenharmony_ci#include <assert.h> 1062306a36Sopenharmony_ci#include <errno.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <sys/types.h> 1362306a36Sopenharmony_ci#include <sys/socket.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <bpf/bpf.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <bpf/libbpf.h> 1862306a36Sopenharmony_ci#include "bpf_insn.h" 1962306a36Sopenharmony_ci#include "sock_example.h" 2062306a36Sopenharmony_ci#include "bpf_util.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define BPF_F_PIN (1 << 0) 2362306a36Sopenharmony_ci#define BPF_F_GET (1 << 1) 2462306a36Sopenharmony_ci#define BPF_F_PIN_GET (BPF_F_PIN | BPF_F_GET) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define BPF_F_KEY (1 << 2) 2762306a36Sopenharmony_ci#define BPF_F_VAL (1 << 3) 2862306a36Sopenharmony_ci#define BPF_F_KEY_VAL (BPF_F_KEY | BPF_F_VAL) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define BPF_M_UNSPEC 0 3162306a36Sopenharmony_ci#define BPF_M_MAP 1 3262306a36Sopenharmony_ci#define BPF_M_PROG 2 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cichar bpf_log_buf[BPF_LOG_BUF_SIZE]; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic void usage(void) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci printf("Usage: fds_example [...]\n"); 3962306a36Sopenharmony_ci printf(" -F <file> File to pin/get object\n"); 4062306a36Sopenharmony_ci printf(" -P |- pin object\n"); 4162306a36Sopenharmony_ci printf(" -G `- get object\n"); 4262306a36Sopenharmony_ci printf(" -m eBPF map mode\n"); 4362306a36Sopenharmony_ci printf(" -k <key> |- map key\n"); 4462306a36Sopenharmony_ci printf(" -v <value> `- map value\n"); 4562306a36Sopenharmony_ci printf(" -p eBPF prog mode\n"); 4662306a36Sopenharmony_ci printf(" -o <object> `- object file\n"); 4762306a36Sopenharmony_ci printf(" -h Display this help.\n"); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic int bpf_prog_create(const char *object) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci static struct bpf_insn insns[] = { 5362306a36Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 1), 5462306a36Sopenharmony_ci BPF_EXIT_INSN(), 5562306a36Sopenharmony_ci }; 5662306a36Sopenharmony_ci size_t insns_cnt = ARRAY_SIZE(insns); 5762306a36Sopenharmony_ci struct bpf_object *obj; 5862306a36Sopenharmony_ci int err; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci if (object) { 6162306a36Sopenharmony_ci obj = bpf_object__open_file(object, NULL); 6262306a36Sopenharmony_ci assert(!libbpf_get_error(obj)); 6362306a36Sopenharmony_ci err = bpf_object__load(obj); 6462306a36Sopenharmony_ci assert(!err); 6562306a36Sopenharmony_ci return bpf_program__fd(bpf_object__next_program(obj, NULL)); 6662306a36Sopenharmony_ci } else { 6762306a36Sopenharmony_ci LIBBPF_OPTS(bpf_prog_load_opts, opts, 6862306a36Sopenharmony_ci .log_buf = bpf_log_buf, 6962306a36Sopenharmony_ci .log_size = BPF_LOG_BUF_SIZE, 7062306a36Sopenharmony_ci ); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci return bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", 7362306a36Sopenharmony_ci insns, insns_cnt, &opts); 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int bpf_do_map(const char *file, uint32_t flags, uint32_t key, 7862306a36Sopenharmony_ci uint32_t value) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci int fd, ret; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (flags & BPF_F_PIN) { 8362306a36Sopenharmony_ci fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(uint32_t), 8462306a36Sopenharmony_ci sizeof(uint32_t), 1024, NULL); 8562306a36Sopenharmony_ci printf("bpf: map fd:%d (%s)\n", fd, strerror(errno)); 8662306a36Sopenharmony_ci assert(fd > 0); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci ret = bpf_obj_pin(fd, file); 8962306a36Sopenharmony_ci printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 9062306a36Sopenharmony_ci assert(ret == 0); 9162306a36Sopenharmony_ci } else { 9262306a36Sopenharmony_ci fd = bpf_obj_get(file); 9362306a36Sopenharmony_ci printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 9462306a36Sopenharmony_ci assert(fd > 0); 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) { 9862306a36Sopenharmony_ci ret = bpf_map_update_elem(fd, &key, &value, 0); 9962306a36Sopenharmony_ci printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value, 10062306a36Sopenharmony_ci ret, strerror(errno)); 10162306a36Sopenharmony_ci assert(ret == 0); 10262306a36Sopenharmony_ci } else if (flags & BPF_F_KEY) { 10362306a36Sopenharmony_ci ret = bpf_map_lookup_elem(fd, &key, &value); 10462306a36Sopenharmony_ci printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value, 10562306a36Sopenharmony_ci ret, strerror(errno)); 10662306a36Sopenharmony_ci assert(ret == 0); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci return 0; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic int bpf_do_prog(const char *file, uint32_t flags, const char *object) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci int fd, sock, ret; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (flags & BPF_F_PIN) { 11762306a36Sopenharmony_ci fd = bpf_prog_create(object); 11862306a36Sopenharmony_ci printf("bpf: prog fd:%d (%s)\n", fd, strerror(errno)); 11962306a36Sopenharmony_ci assert(fd > 0); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci ret = bpf_obj_pin(fd, file); 12262306a36Sopenharmony_ci printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 12362306a36Sopenharmony_ci assert(ret == 0); 12462306a36Sopenharmony_ci } else { 12562306a36Sopenharmony_ci fd = bpf_obj_get(file); 12662306a36Sopenharmony_ci printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 12762306a36Sopenharmony_ci assert(fd > 0); 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci sock = open_raw_sock("lo"); 13162306a36Sopenharmony_ci assert(sock > 0); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &fd, sizeof(fd)); 13462306a36Sopenharmony_ci printf("bpf: sock:%d <- fd:%d attached ret:(%d,%s)\n", sock, fd, 13562306a36Sopenharmony_ci ret, strerror(errno)); 13662306a36Sopenharmony_ci assert(ret == 0); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return 0; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ciint main(int argc, char **argv) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci const char *file = NULL, *object = NULL; 14462306a36Sopenharmony_ci uint32_t key = 0, value = 0, flags = 0; 14562306a36Sopenharmony_ci int opt, mode = BPF_M_UNSPEC; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci while ((opt = getopt(argc, argv, "F:PGmk:v:po:")) != -1) { 14862306a36Sopenharmony_ci switch (opt) { 14962306a36Sopenharmony_ci /* General args */ 15062306a36Sopenharmony_ci case 'F': 15162306a36Sopenharmony_ci file = optarg; 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci case 'P': 15462306a36Sopenharmony_ci flags |= BPF_F_PIN; 15562306a36Sopenharmony_ci break; 15662306a36Sopenharmony_ci case 'G': 15762306a36Sopenharmony_ci flags |= BPF_F_GET; 15862306a36Sopenharmony_ci break; 15962306a36Sopenharmony_ci /* Map-related args */ 16062306a36Sopenharmony_ci case 'm': 16162306a36Sopenharmony_ci mode = BPF_M_MAP; 16262306a36Sopenharmony_ci break; 16362306a36Sopenharmony_ci case 'k': 16462306a36Sopenharmony_ci key = strtoul(optarg, NULL, 0); 16562306a36Sopenharmony_ci flags |= BPF_F_KEY; 16662306a36Sopenharmony_ci break; 16762306a36Sopenharmony_ci case 'v': 16862306a36Sopenharmony_ci value = strtoul(optarg, NULL, 0); 16962306a36Sopenharmony_ci flags |= BPF_F_VAL; 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci /* Prog-related args */ 17262306a36Sopenharmony_ci case 'p': 17362306a36Sopenharmony_ci mode = BPF_M_PROG; 17462306a36Sopenharmony_ci break; 17562306a36Sopenharmony_ci case 'o': 17662306a36Sopenharmony_ci object = optarg; 17762306a36Sopenharmony_ci break; 17862306a36Sopenharmony_ci default: 17962306a36Sopenharmony_ci goto out; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if (!(flags & BPF_F_PIN_GET) || !file) 18462306a36Sopenharmony_ci goto out; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci switch (mode) { 18762306a36Sopenharmony_ci case BPF_M_MAP: 18862306a36Sopenharmony_ci return bpf_do_map(file, flags, key, value); 18962306a36Sopenharmony_ci case BPF_M_PROG: 19062306a36Sopenharmony_ci return bpf_do_prog(file, flags, object); 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ciout: 19362306a36Sopenharmony_ci usage(); 19462306a36Sopenharmony_ci return -1; 19562306a36Sopenharmony_ci} 196