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