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