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