150b3ed57SPetar Penkov // SPDX-License-Identifier: GPL-2.0
250b3ed57SPetar Penkov #include <error.h>
350b3ed57SPetar Penkov #include <errno.h>
450b3ed57SPetar Penkov #include <getopt.h>
550b3ed57SPetar Penkov #include <stdio.h>
650b3ed57SPetar Penkov #include <stdlib.h>
750b3ed57SPetar Penkov #include <string.h>
850b3ed57SPetar Penkov #include <sys/stat.h>
950b3ed57SPetar Penkov #include <fcntl.h>
1050b3ed57SPetar Penkov #include <unistd.h>
1150b3ed57SPetar Penkov #include <bpf/bpf.h>
1250b3ed57SPetar Penkov #include <bpf/libbpf.h>
1350b3ed57SPetar Penkov
14bf0f0fd9SStanislav Fomichev #include "flow_dissector_load.h"
15b31d30d9SYonghong Song
1650b3ed57SPetar Penkov const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector";
1750b3ed57SPetar Penkov const char *cfg_map_name = "jmp_table";
1850b3ed57SPetar Penkov bool cfg_attach = true;
19d1321207SStanislav Fomichev char *cfg_prog_name;
2050b3ed57SPetar Penkov char *cfg_path_name;
2150b3ed57SPetar Penkov
load_and_attach_program(void)2250b3ed57SPetar Penkov static void load_and_attach_program(void)
2350b3ed57SPetar Penkov {
24bf0f0fd9SStanislav Fomichev int prog_fd, ret;
2550b3ed57SPetar Penkov struct bpf_object *obj;
2650b3ed57SPetar Penkov
27*b858ba8cSYafang Shao /* Use libbpf 1.0 API mode */
28*b858ba8cSYafang Shao libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
29d1321207SStanislav Fomichev
30d1321207SStanislav Fomichev ret = bpf_flow_load(&obj, cfg_path_name, cfg_prog_name,
310905beecSStanislav Fomichev cfg_map_name, NULL, &prog_fd, NULL);
3250b3ed57SPetar Penkov if (ret)
33bf0f0fd9SStanislav Fomichev error(1, 0, "bpf_flow_load %s", cfg_path_name);
3450b3ed57SPetar Penkov
3550b3ed57SPetar Penkov ret = bpf_prog_attach(prog_fd, 0 /* Ignore */, BPF_FLOW_DISSECTOR, 0);
3650b3ed57SPetar Penkov if (ret)
3750b3ed57SPetar Penkov error(1, 0, "bpf_prog_attach %s", cfg_path_name);
3850b3ed57SPetar Penkov
3950b3ed57SPetar Penkov ret = bpf_object__pin(obj, cfg_pin_path);
4050b3ed57SPetar Penkov if (ret)
4150b3ed57SPetar Penkov error(1, 0, "bpf_object__pin %s", cfg_pin_path);
4250b3ed57SPetar Penkov }
4350b3ed57SPetar Penkov
detach_program(void)4450b3ed57SPetar Penkov static void detach_program(void)
4550b3ed57SPetar Penkov {
4650b3ed57SPetar Penkov char command[64];
4750b3ed57SPetar Penkov int ret;
4850b3ed57SPetar Penkov
4950b3ed57SPetar Penkov ret = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
5050b3ed57SPetar Penkov if (ret)
5150b3ed57SPetar Penkov error(1, 0, "bpf_prog_detach");
5250b3ed57SPetar Penkov
5350b3ed57SPetar Penkov /* To unpin, it is necessary and sufficient to just remove this dir */
5450b3ed57SPetar Penkov sprintf(command, "rm -r %s", cfg_pin_path);
5550b3ed57SPetar Penkov ret = system(command);
5650b3ed57SPetar Penkov if (ret)
5794e8f3c7SStanislav Fomichev error(1, errno, "%s", command);
5850b3ed57SPetar Penkov }
5950b3ed57SPetar Penkov
parse_opts(int argc,char ** argv)6050b3ed57SPetar Penkov static void parse_opts(int argc, char **argv)
6150b3ed57SPetar Penkov {
6250b3ed57SPetar Penkov bool attach = false;
6350b3ed57SPetar Penkov bool detach = false;
6450b3ed57SPetar Penkov int c;
6550b3ed57SPetar Penkov
6650b3ed57SPetar Penkov while ((c = getopt(argc, argv, "adp:s:")) != -1) {
6750b3ed57SPetar Penkov switch (c) {
6850b3ed57SPetar Penkov case 'a':
6950b3ed57SPetar Penkov if (detach)
7050b3ed57SPetar Penkov error(1, 0, "attach/detach are exclusive");
7150b3ed57SPetar Penkov attach = true;
7250b3ed57SPetar Penkov break;
7350b3ed57SPetar Penkov case 'd':
7450b3ed57SPetar Penkov if (attach)
7550b3ed57SPetar Penkov error(1, 0, "attach/detach are exclusive");
7650b3ed57SPetar Penkov detach = true;
7750b3ed57SPetar Penkov break;
7850b3ed57SPetar Penkov case 'p':
7950b3ed57SPetar Penkov if (cfg_path_name)
80d1321207SStanislav Fomichev error(1, 0, "only one path can be given");
8150b3ed57SPetar Penkov
8250b3ed57SPetar Penkov cfg_path_name = optarg;
8350b3ed57SPetar Penkov break;
8450b3ed57SPetar Penkov case 's':
85d1321207SStanislav Fomichev if (cfg_prog_name)
86d1321207SStanislav Fomichev error(1, 0, "only one prog can be given");
8750b3ed57SPetar Penkov
88d1321207SStanislav Fomichev cfg_prog_name = optarg;
8950b3ed57SPetar Penkov break;
9050b3ed57SPetar Penkov }
9150b3ed57SPetar Penkov }
9250b3ed57SPetar Penkov
9350b3ed57SPetar Penkov if (detach)
9450b3ed57SPetar Penkov cfg_attach = false;
9550b3ed57SPetar Penkov
9650b3ed57SPetar Penkov if (cfg_attach && !cfg_path_name)
9750b3ed57SPetar Penkov error(1, 0, "must provide a path to the BPF program");
9850b3ed57SPetar Penkov
99d1321207SStanislav Fomichev if (cfg_attach && !cfg_prog_name)
10050b3ed57SPetar Penkov error(1, 0, "must provide a section name");
10150b3ed57SPetar Penkov }
10250b3ed57SPetar Penkov
main(int argc,char ** argv)10350b3ed57SPetar Penkov int main(int argc, char **argv)
10450b3ed57SPetar Penkov {
10550b3ed57SPetar Penkov parse_opts(argc, argv);
10650b3ed57SPetar Penkov if (cfg_attach)
10750b3ed57SPetar Penkov load_and_attach_program();
10850b3ed57SPetar Penkov else
10950b3ed57SPetar Penkov detach_program();
11050b3ed57SPetar Penkov return 0;
11150b3ed57SPetar Penkov }
112