]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/m_bpf.c
q_cake: Make fwmark uint instead of int
[mirror_iproute2.git] / tc / m_bpf.c
CommitLineData
86ab59a6 1/*
d937a74b 2 * m_bpf.c BPF based action module
86ab59a6
JP
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>
6256f8c9 10 * Daniel Borkmann <daniel@iogearbox.net>
86ab59a6
JP
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
32e93fb7 15
6256f8c9 16#include <linux/bpf.h>
86ab59a6
JP
17#include <linux/tc_act/tc_bpf.h>
18
19#include "utils.h"
e4225669 20
86ab59a6 21#include "tc_util.h"
e4225669 22#include "bpf_util.h"
86ab59a6 23
6256f8c9
DB
24static const enum bpf_prog_type bpf_type = BPF_PROG_TYPE_SCHED_ACT;
25
86ab59a6
JP
26static void explain(void)
27{
8589eb4e
MC
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));
86ab59a6
JP
56}
57
e4225669
DB
58static 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
65static 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
71static const struct bpf_cfg_ops bpf_cb_ops = {
72 .cbpf_cb = bpf_cbpf_cb,
73 .ebpf_cb = bpf_ebpf_cb,
74};
75
32e93fb7
DB
76static int bpf_parse_opt(struct action_util *a, int *ptr_argc, char ***ptr_argv,
77 int tca_id, struct nlmsghdr *n)
86ab59a6 78{
32e93fb7 79 const char *bpf_obj = NULL, *bpf_uds_name = NULL;
e67aba55 80 struct tc_act_bpf parm = {};
e4225669 81 struct bpf_cfg_in cfg = {};
32e93fb7 82 bool seen_run = false;
86ab59a6 83 struct rtattr *tail;
32e93fb7
DB
84 int argc, ret = 0;
85 char **argv;
86
87 argv = *ptr_argv;
88 argc = *ptr_argc;
86ab59a6
JP
89
90 if (matches(*argv, "bpf") != 0)
91 return -1;
92
93 NEXT_ARG();
94
c14f9d92 95 tail = addattr_nest(n, MAX_MSG, tca_id);
32e93fb7 96
86ab59a6
JP
97 while (argc > 0) {
98 if (matches(*argv, "run") == 0) {
86ab59a6 99 NEXT_ARG();
67c857df
JK
100
101 if (seen_run)
102 duparg("run", *argv);
6256f8c9 103opt_bpf:
6256f8c9 104 seen_run = true;
658cfebc 105 cfg.type = bpf_type;
e4225669
DB
106 cfg.argc = argc;
107 cfg.argv = argv;
108
399db839 109 if (bpf_parse_and_load_common(&cfg, &bpf_cb_ops, n))
86ab59a6 110 return -1;
e4225669
DB
111
112 argc = cfg.argc;
113 argv = cfg.argv;
114
115 bpf_obj = cfg.object;
116 bpf_uds_name = cfg.uds;
86ab59a6 117 } else if (matches(*argv, "help") == 0) {
32e93fb7
DB
118 explain();
119 return -1;
baed9084
DB
120 } else if (matches(*argv, "index") == 0) {
121 break;
86ab59a6 122 } else {
6256f8c9
DB
123 if (!seen_run)
124 goto opt_bpf;
86ab59a6
JP
125 break;
126 }
343dc908
DB
127
128 NEXT_ARG_FWD();
86ab59a6
JP
129 }
130
e67aba55
JP
131 parse_action_control_dflt(&argc, &argv, &parm.action,
132 false, TC_ACT_PIPE);
86ab59a6
JP
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 }
343dc908
DB
141
142 NEXT_ARG_FWD();
86ab59a6
JP
143 }
144 }
145
86ab59a6 146 addattr_l(n, MAX_MSG, TCA_ACT_BPF_PARMS, &parm, sizeof(parm));
c14f9d92 147 addattr_nest_end(n, tail);
86ab59a6 148
6256f8c9 149 if (bpf_uds_name)
4bd62446 150 ret = bpf_send_map_fds(bpf_uds_name, bpf_obj);
6256f8c9 151
32e93fb7
DB
152 *ptr_argc = argc;
153 *ptr_argv = argv;
154
6256f8c9 155 return ret;
86ab59a6
JP
156}
157
32e93fb7 158static int bpf_print_opt(struct action_util *au, FILE *f, struct rtattr *arg)
86ab59a6
JP
159{
160 struct rtattr *tb[TCA_ACT_BPF_MAX + 1];
161 struct tc_act_bpf *parm;
52d57f6b 162 int d_ok = 0;
32a121cb 163
86ab59a6
JP
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]) {
d5ddb441 170 fprintf(stderr, "Missing bpf parameters\n");
86ab59a6
JP
171 return -1;
172 }
6256f8c9 173
86ab59a6 174 parm = RTA_DATA(tb[TCA_ACT_BPF_PARMS]);
52d57f6b 175 print_string(PRINT_ANY, "kind", "%s ", "bpf");
6256f8c9
DB
176
177 if (tb[TCA_ACT_BPF_NAME])
52d57f6b
DC
178 print_string(PRINT_ANY, "bpf_name", "%s ",
179 rta_getattr_str(tb[TCA_ACT_BPF_NAME]));
6256f8c9 180 if (tb[TCA_ACT_BPF_OPS] && tb[TCA_ACT_BPF_OPS_LEN]) {
52d57f6b 181 bpf_print_ops(tb[TCA_ACT_BPF_OPS],
86ab59a6 182 rta_getattr_u16(tb[TCA_ACT_BPF_OPS_LEN]));
52d57f6b 183 print_string(PRINT_FP, NULL, "%s", " ");
6256f8c9 184 }
86ab59a6 185
a0b5b7cf 186 if (tb[TCA_ACT_BPF_ID])
52d57f6b
DC
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]) {
e37d706b
DB
190 SPRINT_BUF(b);
191
52d57f6b
DC
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)));
e37d706b
DB
196 }
197
52d57f6b
DC
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);
86ab59a6
JP
202
203 if (show_stats) {
204 if (tb[TCA_ACT_BPF_TM]) {
205 struct tcf_t *tm = RTA_DATA(tb[TCA_ACT_BPF_TM]);
32a121cb 206
86ab59a6
JP
207 print_tm(f, tm);
208 }
209 }
210
211 fprintf(f, "\n ");
86ab59a6
JP
212 return 0;
213}
214
215struct action_util bpf_action_util = {
32e93fb7
DB
216 .id = "bpf",
217 .parse_aopt = bpf_parse_opt,
218 .print_aopt = bpf_print_opt,
86ab59a6 219};