xref: /linux/tools/testing/selftests/bpf/flow_dissector_load.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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