142984d7cSDaniel Borkmann #include <linux/unistd.h> 242984d7cSDaniel Borkmann #include <linux/bpf.h> 342984d7cSDaniel Borkmann 442984d7cSDaniel Borkmann #include <stdio.h> 542984d7cSDaniel Borkmann #include <stdlib.h> 642984d7cSDaniel Borkmann #include <stdint.h> 742984d7cSDaniel Borkmann #include <unistd.h> 842984d7cSDaniel Borkmann #include <string.h> 942984d7cSDaniel Borkmann #include <assert.h> 1042984d7cSDaniel Borkmann #include <errno.h> 1142984d7cSDaniel Borkmann 1242984d7cSDaniel Borkmann #include <sys/types.h> 1342984d7cSDaniel Borkmann #include <sys/socket.h> 1442984d7cSDaniel Borkmann 1542984d7cSDaniel Borkmann #include "bpf_load.h" 1642984d7cSDaniel Borkmann #include "libbpf.h" 1742984d7cSDaniel Borkmann 1842984d7cSDaniel Borkmann #define BPF_F_PIN (1 << 0) 1942984d7cSDaniel Borkmann #define BPF_F_GET (1 << 1) 2042984d7cSDaniel Borkmann #define BPF_F_PIN_GET (BPF_F_PIN | BPF_F_GET) 2142984d7cSDaniel Borkmann 2242984d7cSDaniel Borkmann #define BPF_F_KEY (1 << 2) 2342984d7cSDaniel Borkmann #define BPF_F_VAL (1 << 3) 2442984d7cSDaniel Borkmann #define BPF_F_KEY_VAL (BPF_F_KEY | BPF_F_VAL) 2542984d7cSDaniel Borkmann 2642984d7cSDaniel Borkmann #define BPF_M_UNSPEC 0 2742984d7cSDaniel Borkmann #define BPF_M_MAP 1 2842984d7cSDaniel Borkmann #define BPF_M_PROG 2 2942984d7cSDaniel Borkmann 3042984d7cSDaniel Borkmann static void usage(void) 3142984d7cSDaniel Borkmann { 3242984d7cSDaniel Borkmann printf("Usage: fds_example [...]\n"); 3342984d7cSDaniel Borkmann printf(" -F <file> File to pin/get object\n"); 3442984d7cSDaniel Borkmann printf(" -P |- pin object\n"); 3542984d7cSDaniel Borkmann printf(" -G `- get object\n"); 3642984d7cSDaniel Borkmann printf(" -m eBPF map mode\n"); 3742984d7cSDaniel Borkmann printf(" -k <key> |- map key\n"); 3842984d7cSDaniel Borkmann printf(" -v <value> `- map value\n"); 3942984d7cSDaniel Borkmann printf(" -p eBPF prog mode\n"); 4042984d7cSDaniel Borkmann printf(" -o <object> `- object file\n"); 4142984d7cSDaniel Borkmann printf(" -h Display this help.\n"); 4242984d7cSDaniel Borkmann } 4342984d7cSDaniel Borkmann 4442984d7cSDaniel Borkmann static int bpf_map_create(void) 4542984d7cSDaniel Borkmann { 4642984d7cSDaniel Borkmann return bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(uint32_t), 4789b97607SAlexei Starovoitov sizeof(uint32_t), 1024, 0); 4842984d7cSDaniel Borkmann } 4942984d7cSDaniel Borkmann 5042984d7cSDaniel Borkmann static int bpf_prog_create(const char *object) 5142984d7cSDaniel Borkmann { 5242984d7cSDaniel Borkmann static const struct bpf_insn insns[] = { 5342984d7cSDaniel Borkmann BPF_MOV64_IMM(BPF_REG_0, 1), 5442984d7cSDaniel Borkmann BPF_EXIT_INSN(), 5542984d7cSDaniel Borkmann }; 5643371c83SJoe Stringer size_t insns_cnt = sizeof(insns) / sizeof(struct bpf_insn); 5742984d7cSDaniel Borkmann 5842984d7cSDaniel Borkmann if (object) { 5942984d7cSDaniel Borkmann assert(!load_bpf_file((char *)object)); 6042984d7cSDaniel Borkmann return prog_fd[0]; 6142984d7cSDaniel Borkmann } else { 62d40fc181SJoe Stringer return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, 6343371c83SJoe Stringer insns, insns_cnt, "GPL", 0, 64d40fc181SJoe Stringer bpf_log_buf, BPF_LOG_BUF_SIZE); 6542984d7cSDaniel Borkmann } 6642984d7cSDaniel Borkmann } 6742984d7cSDaniel Borkmann 6842984d7cSDaniel Borkmann static int bpf_do_map(const char *file, uint32_t flags, uint32_t key, 6942984d7cSDaniel Borkmann uint32_t value) 7042984d7cSDaniel Borkmann { 7142984d7cSDaniel Borkmann int fd, ret; 7242984d7cSDaniel Borkmann 7342984d7cSDaniel Borkmann if (flags & BPF_F_PIN) { 7442984d7cSDaniel Borkmann fd = bpf_map_create(); 7542984d7cSDaniel Borkmann printf("bpf: map fd:%d (%s)\n", fd, strerror(errno)); 7642984d7cSDaniel Borkmann assert(fd > 0); 7742984d7cSDaniel Borkmann 7842984d7cSDaniel Borkmann ret = bpf_obj_pin(fd, file); 7942984d7cSDaniel Borkmann printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 8042984d7cSDaniel Borkmann assert(ret == 0); 8142984d7cSDaniel Borkmann } else { 8242984d7cSDaniel Borkmann fd = bpf_obj_get(file); 8342984d7cSDaniel Borkmann printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 8442984d7cSDaniel Borkmann assert(fd > 0); 8542984d7cSDaniel Borkmann } 8642984d7cSDaniel Borkmann 8742984d7cSDaniel Borkmann if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) { 88d40fc181SJoe Stringer ret = bpf_map_update_elem(fd, &key, &value, 0); 8942984d7cSDaniel Borkmann printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value, 9042984d7cSDaniel Borkmann ret, strerror(errno)); 9142984d7cSDaniel Borkmann assert(ret == 0); 9242984d7cSDaniel Borkmann } else if (flags & BPF_F_KEY) { 93d40fc181SJoe Stringer ret = bpf_map_lookup_elem(fd, &key, &value); 9442984d7cSDaniel Borkmann printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value, 9542984d7cSDaniel Borkmann ret, strerror(errno)); 9642984d7cSDaniel Borkmann assert(ret == 0); 9742984d7cSDaniel Borkmann } 9842984d7cSDaniel Borkmann 9942984d7cSDaniel Borkmann return 0; 10042984d7cSDaniel Borkmann } 10142984d7cSDaniel Borkmann 10242984d7cSDaniel Borkmann static int bpf_do_prog(const char *file, uint32_t flags, const char *object) 10342984d7cSDaniel Borkmann { 10442984d7cSDaniel Borkmann int fd, sock, ret; 10542984d7cSDaniel Borkmann 10642984d7cSDaniel Borkmann if (flags & BPF_F_PIN) { 10742984d7cSDaniel Borkmann fd = bpf_prog_create(object); 10842984d7cSDaniel Borkmann printf("bpf: prog fd:%d (%s)\n", fd, strerror(errno)); 10942984d7cSDaniel Borkmann assert(fd > 0); 11042984d7cSDaniel Borkmann 11142984d7cSDaniel Borkmann ret = bpf_obj_pin(fd, file); 11242984d7cSDaniel Borkmann printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno)); 11342984d7cSDaniel Borkmann assert(ret == 0); 11442984d7cSDaniel Borkmann } else { 11542984d7cSDaniel Borkmann fd = bpf_obj_get(file); 11642984d7cSDaniel Borkmann printf("bpf: get fd:%d (%s)\n", fd, strerror(errno)); 11742984d7cSDaniel Borkmann assert(fd > 0); 11842984d7cSDaniel Borkmann } 11942984d7cSDaniel Borkmann 12042984d7cSDaniel Borkmann sock = open_raw_sock("lo"); 12142984d7cSDaniel Borkmann assert(sock > 0); 12242984d7cSDaniel Borkmann 12342984d7cSDaniel Borkmann ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &fd, sizeof(fd)); 12442984d7cSDaniel Borkmann printf("bpf: sock:%d <- fd:%d attached ret:(%d,%s)\n", sock, fd, 12542984d7cSDaniel Borkmann ret, strerror(errno)); 12642984d7cSDaniel Borkmann assert(ret == 0); 12742984d7cSDaniel Borkmann 12842984d7cSDaniel Borkmann return 0; 12942984d7cSDaniel Borkmann } 13042984d7cSDaniel Borkmann 13142984d7cSDaniel Borkmann int main(int argc, char **argv) 13242984d7cSDaniel Borkmann { 13342984d7cSDaniel Borkmann const char *file = NULL, *object = NULL; 13442984d7cSDaniel Borkmann uint32_t key = 0, value = 0, flags = 0; 13542984d7cSDaniel Borkmann int opt, mode = BPF_M_UNSPEC; 13642984d7cSDaniel Borkmann 13742984d7cSDaniel Borkmann while ((opt = getopt(argc, argv, "F:PGmk:v:po:")) != -1) { 13842984d7cSDaniel Borkmann switch (opt) { 13942984d7cSDaniel Borkmann /* General args */ 14042984d7cSDaniel Borkmann case 'F': 14142984d7cSDaniel Borkmann file = optarg; 14242984d7cSDaniel Borkmann break; 14342984d7cSDaniel Borkmann case 'P': 14442984d7cSDaniel Borkmann flags |= BPF_F_PIN; 14542984d7cSDaniel Borkmann break; 14642984d7cSDaniel Borkmann case 'G': 14742984d7cSDaniel Borkmann flags |= BPF_F_GET; 14842984d7cSDaniel Borkmann break; 14942984d7cSDaniel Borkmann /* Map-related args */ 15042984d7cSDaniel Borkmann case 'm': 15142984d7cSDaniel Borkmann mode = BPF_M_MAP; 15242984d7cSDaniel Borkmann break; 15342984d7cSDaniel Borkmann case 'k': 15442984d7cSDaniel Borkmann key = strtoul(optarg, NULL, 0); 15542984d7cSDaniel Borkmann flags |= BPF_F_KEY; 15642984d7cSDaniel Borkmann break; 15742984d7cSDaniel Borkmann case 'v': 15842984d7cSDaniel Borkmann value = strtoul(optarg, NULL, 0); 15942984d7cSDaniel Borkmann flags |= BPF_F_VAL; 16042984d7cSDaniel Borkmann break; 16142984d7cSDaniel Borkmann /* Prog-related args */ 16242984d7cSDaniel Borkmann case 'p': 16342984d7cSDaniel Borkmann mode = BPF_M_PROG; 16442984d7cSDaniel Borkmann break; 16542984d7cSDaniel Borkmann case 'o': 16642984d7cSDaniel Borkmann object = optarg; 16742984d7cSDaniel Borkmann break; 16842984d7cSDaniel Borkmann default: 16942984d7cSDaniel Borkmann goto out; 17042984d7cSDaniel Borkmann } 17142984d7cSDaniel Borkmann } 17242984d7cSDaniel Borkmann 17342984d7cSDaniel Borkmann if (!(flags & BPF_F_PIN_GET) || !file) 17442984d7cSDaniel Borkmann goto out; 17542984d7cSDaniel Borkmann 17642984d7cSDaniel Borkmann switch (mode) { 17742984d7cSDaniel Borkmann case BPF_M_MAP: 17842984d7cSDaniel Borkmann return bpf_do_map(file, flags, key, value); 17942984d7cSDaniel Borkmann case BPF_M_PROG: 18042984d7cSDaniel Borkmann return bpf_do_prog(file, flags, object); 18142984d7cSDaniel Borkmann } 18242984d7cSDaniel Borkmann out: 18342984d7cSDaniel Borkmann usage(); 18442984d7cSDaniel Borkmann return -1; 18542984d7cSDaniel Borkmann } 186