unet-cli: strip initial newline in usage message
[project/unetd.git] / bpf.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
4 */
5 #define _GNU_SOURCE
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <sys/resource.h>
9 #include <netinet/if_ether.h>
10 #include <netlink/msg.h>
11 #include <netlink/attr.h>
12 #include <netlink/socket.h>
13 #include <linux/rtnetlink.h>
14 #include <linux/pkt_cls.h>
15 #include <bpf/bpf.h>
16 #include <bpf/libbpf.h>
17 #include "unetd.h"
18
19 static int unetd_bpf_pr(enum libbpf_print_level level, const char *format,
20 va_list args)
21 {
22 return vfprintf(stderr, format, args);
23 }
24
25 static void unetd_init_env(void)
26 {
27 struct rlimit limit = {
28 .rlim_cur = RLIM_INFINITY,
29 .rlim_max = RLIM_INFINITY,
30 };
31
32 setrlimit(RLIMIT_MEMLOCK, &limit);
33 }
34
35 static void
36 unetd_set_prog_mtu(struct bpf_object *obj, uint32_t mtu)
37 {
38 struct bpf_map *map = NULL;
39
40 while ((map = bpf_object__next_map(obj, map)) != NULL) {
41 if (!strstr(bpf_map__name(map), ".rodata"))
42 continue;
43
44 bpf_map__set_initial_value(map, &mtu, sizeof(mtu));
45 }
46 }
47
48 static int
49 unetd_attach_bpf_prog(int ifindex, int fd, bool egress)
50 {
51 DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook,
52 .attach_point = egress ? BPF_TC_EGRESS : BPF_TC_INGRESS,
53 .ifindex = ifindex);
54 DECLARE_LIBBPF_OPTS(bpf_tc_opts, attach_tc,
55 .flags = BPF_TC_F_REPLACE,
56 .handle = 1,
57 .prog_fd = fd,
58 .priority = UNETD_MSS_PRIO_BASE);
59
60 bpf_tc_hook_create(&hook);
61
62 return bpf_tc_attach(&hook, &attach_tc);
63 }
64
65 int unetd_attach_mssfix(int ifindex, int mtu)
66 {
67 struct bpf_program *prog;
68 struct bpf_object *obj;
69 int prog_fd;
70 int ret = -1;
71
72 if (rtnl_init())
73 return -1;
74
75 unetd_init_env();
76 libbpf_set_print(unetd_bpf_pr);
77
78 obj = bpf_object__open_file(mssfix_path, NULL);
79 if (libbpf_get_error(obj)) {
80 perror("bpf_object__open_file");
81 goto out;
82 }
83
84 prog = bpf_object__find_program_by_name(obj, "mssfix");
85 if (!prog) {
86 perror("bpf_object__find_program_by_name");
87 goto out;
88 }
89
90 bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS);
91
92 unetd_set_prog_mtu(obj, mtu);
93
94 if (bpf_object__load(obj)) {
95 perror("bpf_object__load");
96 goto out;
97 }
98
99 prog_fd = bpf_program__fd(prog);
100 unetd_attach_bpf_prog(ifindex, prog_fd, true);
101 unetd_attach_bpf_prog(ifindex, prog_fd, false);
102
103 ret = 0;
104
105 out:
106 bpf_object__close(obj);
107
108 return ret;
109 }