xref: /OK3568_Linux_fs/kernel/samples/bpf/fds_example.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun #include <linux/unistd.h>
2*4882a593Smuzhiyun #include <linux/bpf.h>
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <stdio.h>
5*4882a593Smuzhiyun #include <stdlib.h>
6*4882a593Smuzhiyun #include <stdint.h>
7*4882a593Smuzhiyun #include <unistd.h>
8*4882a593Smuzhiyun #include <string.h>
9*4882a593Smuzhiyun #include <assert.h>
10*4882a593Smuzhiyun #include <errno.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <sys/types.h>
13*4882a593Smuzhiyun #include <sys/socket.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <bpf/bpf.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <bpf/libbpf.h>
18*4882a593Smuzhiyun #include "bpf_insn.h"
19*4882a593Smuzhiyun #include "sock_example.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define BPF_F_PIN	(1 << 0)
22*4882a593Smuzhiyun #define BPF_F_GET	(1 << 1)
23*4882a593Smuzhiyun #define BPF_F_PIN_GET	(BPF_F_PIN | BPF_F_GET)
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define BPF_F_KEY	(1 << 2)
26*4882a593Smuzhiyun #define BPF_F_VAL	(1 << 3)
27*4882a593Smuzhiyun #define BPF_F_KEY_VAL	(BPF_F_KEY | BPF_F_VAL)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define BPF_M_UNSPEC	0
30*4882a593Smuzhiyun #define BPF_M_MAP	1
31*4882a593Smuzhiyun #define BPF_M_PROG	2
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun char bpf_log_buf[BPF_LOG_BUF_SIZE];
34*4882a593Smuzhiyun 
usage(void)35*4882a593Smuzhiyun static void usage(void)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun 	printf("Usage: fds_example [...]\n");
38*4882a593Smuzhiyun 	printf("       -F <file>   File to pin/get object\n");
39*4882a593Smuzhiyun 	printf("       -P          |- pin object\n");
40*4882a593Smuzhiyun 	printf("       -G          `- get object\n");
41*4882a593Smuzhiyun 	printf("       -m          eBPF map mode\n");
42*4882a593Smuzhiyun 	printf("       -k <key>    |- map key\n");
43*4882a593Smuzhiyun 	printf("       -v <value>  `- map value\n");
44*4882a593Smuzhiyun 	printf("       -p          eBPF prog mode\n");
45*4882a593Smuzhiyun 	printf("       -o <object> `- object file\n");
46*4882a593Smuzhiyun 	printf("       -h          Display this help.\n");
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
bpf_map_create(void)49*4882a593Smuzhiyun static int bpf_map_create(void)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	return bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(uint32_t),
52*4882a593Smuzhiyun 			      sizeof(uint32_t), 1024, 0);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
bpf_prog_create(const char * object)55*4882a593Smuzhiyun static int bpf_prog_create(const char *object)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun 	static struct bpf_insn insns[] = {
58*4882a593Smuzhiyun 		BPF_MOV64_IMM(BPF_REG_0, 1),
59*4882a593Smuzhiyun 		BPF_EXIT_INSN(),
60*4882a593Smuzhiyun 	};
61*4882a593Smuzhiyun 	size_t insns_cnt = sizeof(insns) / sizeof(struct bpf_insn);
62*4882a593Smuzhiyun 	struct bpf_object *obj;
63*4882a593Smuzhiyun 	int prog_fd;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	if (object) {
66*4882a593Smuzhiyun 		assert(!bpf_prog_load(object, BPF_PROG_TYPE_UNSPEC,
67*4882a593Smuzhiyun 				      &obj, &prog_fd));
68*4882a593Smuzhiyun 		return prog_fd;
69*4882a593Smuzhiyun 	} else {
70*4882a593Smuzhiyun 		return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER,
71*4882a593Smuzhiyun 					insns, insns_cnt, "GPL", 0,
72*4882a593Smuzhiyun 					bpf_log_buf, BPF_LOG_BUF_SIZE);
73*4882a593Smuzhiyun 	}
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
bpf_do_map(const char * file,uint32_t flags,uint32_t key,uint32_t value)76*4882a593Smuzhiyun static int bpf_do_map(const char *file, uint32_t flags, uint32_t key,
77*4882a593Smuzhiyun 		      uint32_t value)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	int fd, ret;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	if (flags & BPF_F_PIN) {
82*4882a593Smuzhiyun 		fd = bpf_map_create();
83*4882a593Smuzhiyun 		printf("bpf: map fd:%d (%s)\n", fd, strerror(errno));
84*4882a593Smuzhiyun 		assert(fd > 0);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 		ret = bpf_obj_pin(fd, file);
87*4882a593Smuzhiyun 		printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno));
88*4882a593Smuzhiyun 		assert(ret == 0);
89*4882a593Smuzhiyun 	} else {
90*4882a593Smuzhiyun 		fd = bpf_obj_get(file);
91*4882a593Smuzhiyun 		printf("bpf: get fd:%d (%s)\n", fd, strerror(errno));
92*4882a593Smuzhiyun 		assert(fd > 0);
93*4882a593Smuzhiyun 	}
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	if ((flags & BPF_F_KEY_VAL) == BPF_F_KEY_VAL) {
96*4882a593Smuzhiyun 		ret = bpf_map_update_elem(fd, &key, &value, 0);
97*4882a593Smuzhiyun 		printf("bpf: fd:%d u->(%u:%u) ret:(%d,%s)\n", fd, key, value,
98*4882a593Smuzhiyun 		       ret, strerror(errno));
99*4882a593Smuzhiyun 		assert(ret == 0);
100*4882a593Smuzhiyun 	} else if (flags & BPF_F_KEY) {
101*4882a593Smuzhiyun 		ret = bpf_map_lookup_elem(fd, &key, &value);
102*4882a593Smuzhiyun 		printf("bpf: fd:%d l->(%u):%u ret:(%d,%s)\n", fd, key, value,
103*4882a593Smuzhiyun 		       ret, strerror(errno));
104*4882a593Smuzhiyun 		assert(ret == 0);
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	return 0;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun 
bpf_do_prog(const char * file,uint32_t flags,const char * object)110*4882a593Smuzhiyun static int bpf_do_prog(const char *file, uint32_t flags, const char *object)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	int fd, sock, ret;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	if (flags & BPF_F_PIN) {
115*4882a593Smuzhiyun 		fd = bpf_prog_create(object);
116*4882a593Smuzhiyun 		printf("bpf: prog fd:%d (%s)\n", fd, strerror(errno));
117*4882a593Smuzhiyun 		assert(fd > 0);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 		ret = bpf_obj_pin(fd, file);
120*4882a593Smuzhiyun 		printf("bpf: pin ret:(%d,%s)\n", ret, strerror(errno));
121*4882a593Smuzhiyun 		assert(ret == 0);
122*4882a593Smuzhiyun 	} else {
123*4882a593Smuzhiyun 		fd = bpf_obj_get(file);
124*4882a593Smuzhiyun 		printf("bpf: get fd:%d (%s)\n", fd, strerror(errno));
125*4882a593Smuzhiyun 		assert(fd > 0);
126*4882a593Smuzhiyun 	}
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	sock = open_raw_sock("lo");
129*4882a593Smuzhiyun 	assert(sock > 0);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &fd, sizeof(fd));
132*4882a593Smuzhiyun 	printf("bpf: sock:%d <- fd:%d attached ret:(%d,%s)\n", sock, fd,
133*4882a593Smuzhiyun 	       ret, strerror(errno));
134*4882a593Smuzhiyun 	assert(ret == 0);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	return 0;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
main(int argc,char ** argv)139*4882a593Smuzhiyun int main(int argc, char **argv)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun 	const char *file = NULL, *object = NULL;
142*4882a593Smuzhiyun 	uint32_t key = 0, value = 0, flags = 0;
143*4882a593Smuzhiyun 	int opt, mode = BPF_M_UNSPEC;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	while ((opt = getopt(argc, argv, "F:PGmk:v:po:")) != -1) {
146*4882a593Smuzhiyun 		switch (opt) {
147*4882a593Smuzhiyun 		/* General args */
148*4882a593Smuzhiyun 		case 'F':
149*4882a593Smuzhiyun 			file = optarg;
150*4882a593Smuzhiyun 			break;
151*4882a593Smuzhiyun 		case 'P':
152*4882a593Smuzhiyun 			flags |= BPF_F_PIN;
153*4882a593Smuzhiyun 			break;
154*4882a593Smuzhiyun 		case 'G':
155*4882a593Smuzhiyun 			flags |= BPF_F_GET;
156*4882a593Smuzhiyun 			break;
157*4882a593Smuzhiyun 		/* Map-related args */
158*4882a593Smuzhiyun 		case 'm':
159*4882a593Smuzhiyun 			mode = BPF_M_MAP;
160*4882a593Smuzhiyun 			break;
161*4882a593Smuzhiyun 		case 'k':
162*4882a593Smuzhiyun 			key = strtoul(optarg, NULL, 0);
163*4882a593Smuzhiyun 			flags |= BPF_F_KEY;
164*4882a593Smuzhiyun 			break;
165*4882a593Smuzhiyun 		case 'v':
166*4882a593Smuzhiyun 			value = strtoul(optarg, NULL, 0);
167*4882a593Smuzhiyun 			flags |= BPF_F_VAL;
168*4882a593Smuzhiyun 			break;
169*4882a593Smuzhiyun 		/* Prog-related args */
170*4882a593Smuzhiyun 		case 'p':
171*4882a593Smuzhiyun 			mode = BPF_M_PROG;
172*4882a593Smuzhiyun 			break;
173*4882a593Smuzhiyun 		case 'o':
174*4882a593Smuzhiyun 			object = optarg;
175*4882a593Smuzhiyun 			break;
176*4882a593Smuzhiyun 		default:
177*4882a593Smuzhiyun 			goto out;
178*4882a593Smuzhiyun 		}
179*4882a593Smuzhiyun 	}
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	if (!(flags & BPF_F_PIN_GET) || !file)
182*4882a593Smuzhiyun 		goto out;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	switch (mode) {
185*4882a593Smuzhiyun 	case BPF_M_MAP:
186*4882a593Smuzhiyun 		return bpf_do_map(file, flags, key, value);
187*4882a593Smuzhiyun 	case BPF_M_PROG:
188*4882a593Smuzhiyun 		return bpf_do_prog(file, flags, object);
189*4882a593Smuzhiyun 	}
190*4882a593Smuzhiyun out:
191*4882a593Smuzhiyun 	usage();
192*4882a593Smuzhiyun 	return -1;
193*4882a593Smuzhiyun }
194