Fix build break in 64bit architectures
[platform/upstream/iproute2.git] / tc / m_bpf.c
1 /*
2  * m_bpf.c      BPF based action module
3  *
4  *              This program is free software; you can redistribute it and/or
5  *              modify it under the terms of the GNU General Public License
6  *              as published by the Free Software Foundation; either version
7  *              2 of the License, or (at your option) any later version.
8  *
9  * Authors:     Jiri Pirko <jiri@resnulli.us>
10  *              Daniel Borkmann <daniel@iogearbox.net>
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15
16 #include <linux/bpf.h>
17 #include <linux/tc_act/tc_bpf.h>
18
19 #include "utils.h"
20
21 #include "tc_util.h"
22 #include "bpf_util.h"
23
24 static const enum bpf_prog_type bpf_type = BPF_PROG_TYPE_SCHED_ACT;
25
26 static void explain(void)
27 {
28         fprintf(stderr,
29                 "Usage: ... bpf ... [ index INDEX ]\n"
30                 "\n"
31                 "BPF use case:\n"
32                 " bytecode BPF_BYTECODE\n"
33                 " bytecode-file FILE\n"
34                 "\n"
35                 "eBPF use case:\n"
36                 " object-file FILE [ section ACT_NAME ] [ export UDS_FILE ]"
37                 " [ verbose ]\n"
38                 " object-pinned FILE\n"
39                 "\n"
40                 "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n"
41                 "c,t,f,k and s are decimals; s denotes number of 4-tuples\n"
42                 "\n"
43                 "Where FILE points to a file containing the BPF_BYTECODE string,\n"
44                 "an ELF file containing eBPF map definitions and bytecode, or a\n"
45                 "pinned eBPF program.\n"
46                 "\n"
47                 "Where ACT_NAME refers to the section name containing the\n"
48                 "action (default \'%s\').\n"
49                 "\n"
50                 "Where UDS_FILE points to a unix domain socket file in order\n"
51                 "to hand off control of all created eBPF maps to an agent.\n"
52                 "\n"
53                 "Where optionally INDEX points to an existing action, or\n"
54                 "explicitly specifies an action index upon creation.\n",
55                 bpf_prog_to_default_section(bpf_type));
56 }
57
58 static void bpf_cbpf_cb(void *nl, const struct sock_filter *ops, int ops_len)
59 {
60         addattr16(nl, MAX_MSG, TCA_ACT_BPF_OPS_LEN, ops_len);
61         addattr_l(nl, MAX_MSG, TCA_ACT_BPF_OPS, ops,
62                   ops_len * sizeof(struct sock_filter));
63 }
64
65 static void bpf_ebpf_cb(void *nl, int fd, const char *annotation)
66 {
67         addattr32(nl, MAX_MSG, TCA_ACT_BPF_FD, fd);
68         addattrstrz(nl, MAX_MSG, TCA_ACT_BPF_NAME, annotation);
69 }
70
71 static const struct bpf_cfg_ops bpf_cb_ops = {
72         .cbpf_cb = bpf_cbpf_cb,
73         .ebpf_cb = bpf_ebpf_cb,
74 };
75
76 static int bpf_parse_opt(struct action_util *a, int *ptr_argc, char ***ptr_argv,
77                          int tca_id, struct nlmsghdr *n)
78 {
79         const char *bpf_obj = NULL, *bpf_uds_name = NULL;
80         struct tc_act_bpf parm = {};
81         struct bpf_cfg_in cfg = {};
82         bool seen_run = false;
83         struct rtattr *tail;
84         int argc, ret = 0;
85         char **argv;
86
87         argv = *ptr_argv;
88         argc = *ptr_argc;
89
90         if (matches(*argv, "bpf") != 0)
91                 return -1;
92
93         NEXT_ARG();
94
95         tail = addattr_nest(n, MAX_MSG, tca_id);
96
97         while (argc > 0) {
98                 if (matches(*argv, "run") == 0) {
99                         NEXT_ARG();
100
101                         if (seen_run)
102                                 duparg("run", *argv);
103 opt_bpf:
104                         seen_run = true;
105                         cfg.type = bpf_type;
106                         cfg.argc = argc;
107                         cfg.argv = argv;
108
109                         if (bpf_parse_and_load_common(&cfg, &bpf_cb_ops, n))
110                                 return -1;
111
112                         argc = cfg.argc;
113                         argv = cfg.argv;
114
115                         bpf_obj = cfg.object;
116                         bpf_uds_name = cfg.uds;
117                 } else if (matches(*argv, "help") == 0) {
118                         explain();
119                         return -1;
120                 } else if (matches(*argv, "index") == 0) {
121                         break;
122                 } else {
123                         if (!seen_run)
124                                 goto opt_bpf;
125                         break;
126                 }
127
128                 NEXT_ARG_FWD();
129         }
130
131         parse_action_control_dflt(&argc, &argv, &parm.action,
132                                   false, TC_ACT_PIPE);
133
134         if (argc) {
135                 if (matches(*argv, "index") == 0) {
136                         NEXT_ARG();
137                         if (get_u32(&parm.index, *argv, 10)) {
138                                 fprintf(stderr, "bpf: Illegal \"index\"\n");
139                                 return -1;
140                         }
141
142                         NEXT_ARG_FWD();
143                 }
144         }
145
146         addattr_l(n, MAX_MSG, TCA_ACT_BPF_PARMS, &parm, sizeof(parm));
147         addattr_nest_end(n, tail);
148
149         if (bpf_uds_name)
150                 ret = bpf_send_map_fds(bpf_uds_name, bpf_obj);
151
152         *ptr_argc = argc;
153         *ptr_argv = argv;
154
155         return ret;
156 }
157
158 static int bpf_print_opt(struct action_util *au, FILE *f, struct rtattr *arg)
159 {
160         struct rtattr *tb[TCA_ACT_BPF_MAX + 1];
161         struct tc_act_bpf *parm;
162         int d_ok = 0;
163
164         if (arg == NULL)
165                 return -1;
166
167         parse_rtattr_nested(tb, TCA_ACT_BPF_MAX, arg);
168
169         if (!tb[TCA_ACT_BPF_PARMS]) {
170                 fprintf(stderr, "Missing bpf parameters\n");
171                 return -1;
172         }
173
174         parm = RTA_DATA(tb[TCA_ACT_BPF_PARMS]);
175         print_string(PRINT_ANY, "kind", "%s ", "bpf");
176
177         if (tb[TCA_ACT_BPF_NAME])
178                 print_string(PRINT_ANY, "bpf_name", "%s ",
179                              rta_getattr_str(tb[TCA_ACT_BPF_NAME]));
180         if (tb[TCA_ACT_BPF_OPS] && tb[TCA_ACT_BPF_OPS_LEN]) {
181                 bpf_print_ops(tb[TCA_ACT_BPF_OPS],
182                               rta_getattr_u16(tb[TCA_ACT_BPF_OPS_LEN]));
183                 print_string(PRINT_FP, NULL, "%s", " ");
184         }
185
186         if (tb[TCA_ACT_BPF_ID])
187                 d_ok = bpf_dump_prog_info(f,
188                                           rta_getattr_u32(tb[TCA_ACT_BPF_ID]));
189         if (!d_ok && tb[TCA_ACT_BPF_TAG]) {
190                 SPRINT_BUF(b);
191
192                 print_string(PRINT_ANY, "tag", "tag %s ",
193                              hexstring_n2a(RTA_DATA(tb[TCA_ACT_BPF_TAG]),
194                              RTA_PAYLOAD(tb[TCA_ACT_BPF_TAG]),
195                              b, sizeof(b)));
196         }
197
198         print_action_control(f, "default-action ", parm->action, _SL_);
199         print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
200         print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
201         print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
202
203         if (show_stats) {
204                 if (tb[TCA_ACT_BPF_TM]) {
205                         struct tcf_t *tm = RTA_DATA(tb[TCA_ACT_BPF_TM]);
206
207                         print_tm(f, tm);
208                 }
209         }
210
211         fprintf(f, "\n ");
212         return 0;
213 }
214
215 struct action_util bpf_action_util = {
216         .id             = "bpf",
217         .parse_aopt     = bpf_parse_opt,
218         .print_aopt     = bpf_print_opt,
219 };