Merge branch '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net...
[muen/linux.git] / tools / testing / selftests / bpf / flow_dissector_load.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <error.h>
3 #include <errno.h>
4 #include <getopt.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <bpf/bpf.h>
12 #include <bpf/libbpf.h>
13
14 #include "bpf_rlimit.h"
15
16 const char *cfg_pin_path = "/sys/fs/bpf/flow_dissector";
17 const char *cfg_map_name = "jmp_table";
18 bool cfg_attach = true;
19 char *cfg_section_name;
20 char *cfg_path_name;
21
22 static void load_and_attach_program(void)
23 {
24         struct bpf_program *prog, *main_prog;
25         struct bpf_map *prog_array;
26         int i, fd, prog_fd, ret;
27         struct bpf_object *obj;
28         int prog_array_fd;
29
30         ret = bpf_prog_load(cfg_path_name, BPF_PROG_TYPE_FLOW_DISSECTOR, &obj,
31                             &prog_fd);
32         if (ret)
33                 error(1, 0, "bpf_prog_load %s", cfg_path_name);
34
35         main_prog = bpf_object__find_program_by_title(obj, cfg_section_name);
36         if (!main_prog)
37                 error(1, 0, "bpf_object__find_program_by_title %s",
38                       cfg_section_name);
39
40         prog_fd = bpf_program__fd(main_prog);
41         if (prog_fd < 0)
42                 error(1, 0, "bpf_program__fd");
43
44         prog_array = bpf_object__find_map_by_name(obj, cfg_map_name);
45         if (!prog_array)
46                 error(1, 0, "bpf_object__find_map_by_name %s", cfg_map_name);
47
48         prog_array_fd = bpf_map__fd(prog_array);
49         if (prog_array_fd < 0)
50                 error(1, 0, "bpf_map__fd %s", cfg_map_name);
51
52         i = 0;
53         bpf_object__for_each_program(prog, obj) {
54                 fd = bpf_program__fd(prog);
55                 if (fd < 0)
56                         error(1, 0, "bpf_program__fd");
57
58                 if (fd != prog_fd) {
59                         printf("%d: %s\n", i, bpf_program__title(prog, false));
60                         bpf_map_update_elem(prog_array_fd, &i, &fd, BPF_ANY);
61                         ++i;
62                 }
63         }
64
65         ret = bpf_prog_attach(prog_fd, 0 /* Ignore */, BPF_FLOW_DISSECTOR, 0);
66         if (ret)
67                 error(1, 0, "bpf_prog_attach %s", cfg_path_name);
68
69         ret = bpf_object__pin(obj, cfg_pin_path);
70         if (ret)
71                 error(1, 0, "bpf_object__pin %s", cfg_pin_path);
72
73 }
74
75 static void detach_program(void)
76 {
77         char command[64];
78         int ret;
79
80         ret = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
81         if (ret)
82                 error(1, 0, "bpf_prog_detach");
83
84         /* To unpin, it is necessary and sufficient to just remove this dir */
85         sprintf(command, "rm -r %s", cfg_pin_path);
86         ret = system(command);
87         if (ret)
88                 error(1, errno, command);
89 }
90
91 static void parse_opts(int argc, char **argv)
92 {
93         bool attach = false;
94         bool detach = false;
95         int c;
96
97         while ((c = getopt(argc, argv, "adp:s:")) != -1) {
98                 switch (c) {
99                 case 'a':
100                         if (detach)
101                                 error(1, 0, "attach/detach are exclusive");
102                         attach = true;
103                         break;
104                 case 'd':
105                         if (attach)
106                                 error(1, 0, "attach/detach are exclusive");
107                         detach = true;
108                         break;
109                 case 'p':
110                         if (cfg_path_name)
111                                 error(1, 0, "only one prog name can be given");
112
113                         cfg_path_name = optarg;
114                         break;
115                 case 's':
116                         if (cfg_section_name)
117                                 error(1, 0, "only one section can be given");
118
119                         cfg_section_name = optarg;
120                         break;
121                 }
122         }
123
124         if (detach)
125                 cfg_attach = false;
126
127         if (cfg_attach && !cfg_path_name)
128                 error(1, 0, "must provide a path to the BPF program");
129
130         if (cfg_attach && !cfg_section_name)
131                 error(1, 0, "must provide a section name");
132 }
133
134 int main(int argc, char **argv)
135 {
136         parse_opts(argc, argv);
137         if (cfg_attach)
138                 load_and_attach_program();
139         else
140                 detach_program();
141         return 0;
142 }