2 * f_bpf.c BPF-based Classifier
4 * This program is free software; you can distribute 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.
9 * Authors: Daniel Borkmann <daniel@iogearbox.net>
15 #include <linux/bpf.h>
22 static const enum bpf_prog_type bpf_type
= BPF_PROG_TYPE_SCHED_CLS
;
24 static void explain(void)
27 "Usage: ... bpf ...\n"
30 " bytecode BPF_BYTECODE\n"
31 " bytecode-file FILE\n"
34 " object-file FILE [ section CLS_NAME ] [ export UDS_FILE ]"
35 " [ verbose ] [ direct-action ] [ skip_hw | skip_sw ]\n"
36 " object-pinned FILE [ direct-action ] [ skip_hw | skip_sw ]\n"
38 "Common remaining options:\n"
39 " [ action ACTION_SPEC ]\n"
40 " [ classid CLASSID ]\n"
42 "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n"
43 "c,t,f,k and s are decimals; s denotes number of 4-tuples\n"
45 "Where FILE points to a file containing the BPF_BYTECODE string,\n"
46 "an ELF file containing eBPF map definitions and bytecode, or a\n"
47 "pinned eBPF program.\n"
49 "Where CLS_NAME refers to the section name containing the\n"
50 "classifier (default \'%s\').\n"
52 "Where UDS_FILE points to a unix domain socket file in order\n"
53 "to hand off control of all created eBPF maps to an agent.\n"
55 "ACTION_SPEC := ... look at individual actions\n"
56 "NOTE: CLASSID is parsed as hexadecimal input.\n",
57 bpf_prog_to_default_section(bpf_type
));
60 static void bpf_cbpf_cb(void *nl
, const struct sock_filter
*ops
, int ops_len
)
62 addattr16(nl
, MAX_MSG
, TCA_BPF_OPS_LEN
, ops_len
);
63 addattr_l(nl
, MAX_MSG
, TCA_BPF_OPS
, ops
,
64 ops_len
* sizeof(struct sock_filter
));
67 static void bpf_ebpf_cb(void *nl
, int fd
, const char *annotation
)
69 addattr32(nl
, MAX_MSG
, TCA_BPF_FD
, fd
);
70 addattrstrz(nl
, MAX_MSG
, TCA_BPF_NAME
, annotation
);
73 static const struct bpf_cfg_ops bpf_cb_ops
= {
74 .cbpf_cb
= bpf_cbpf_cb
,
75 .ebpf_cb
= bpf_ebpf_cb
,
78 static int bpf_parse_opt(struct filter_util
*qu
, char *handle
,
79 int argc
, char **argv
, struct nlmsghdr
*n
)
81 const char *bpf_obj
= NULL
, *bpf_uds_name
= NULL
;
82 struct tcmsg
*t
= NLMSG_DATA(n
);
83 unsigned int bpf_gen_flags
= 0;
84 unsigned int bpf_flags
= 0;
85 struct bpf_cfg_in cfg
= {};
86 bool seen_run
= false;
92 if (get_u32(&t
->tcm_handle
, handle
, 0)) {
93 fprintf(stderr
, "Illegal \"handle\"\n");
101 tail
= (struct rtattr
*)(((void *)n
) + NLMSG_ALIGN(n
->nlmsg_len
));
102 addattr_l(n
, MAX_MSG
, TCA_OPTIONS
, NULL
, 0);
105 if (matches(*argv
, "run") == 0) {
109 duparg("run", *argv
);
116 if (bpf_parse_common(&cfg
, &bpf_cb_ops
) < 0) {
118 "Unable to parse bpf command line\n");
125 bpf_obj
= cfg
.object
;
126 bpf_uds_name
= cfg
.uds
;
127 } else if (matches(*argv
, "classid") == 0 ||
128 matches(*argv
, "flowid") == 0) {
132 if (get_tc_classid(&handle
, *argv
)) {
133 fprintf(stderr
, "Illegal \"classid\"\n");
136 addattr32(n
, MAX_MSG
, TCA_BPF_CLASSID
, handle
);
137 } else if (matches(*argv
, "direct-action") == 0 ||
138 matches(*argv
, "da") == 0) {
139 bpf_flags
|= TCA_BPF_FLAG_ACT_DIRECT
;
140 } else if (matches(*argv
, "skip_hw") == 0) {
141 bpf_gen_flags
|= TCA_CLS_FLAGS_SKIP_HW
;
142 } else if (matches(*argv
, "skip_sw") == 0) {
143 bpf_gen_flags
|= TCA_CLS_FLAGS_SKIP_SW
;
145 } else if (matches(*argv
, "action") == 0) {
147 if (parse_action(&argc
, &argv
, TCA_BPF_ACT
, n
)) {
148 fprintf(stderr
, "Illegal \"action\"\n");
152 } else if (matches(*argv
, "police") == 0) {
154 if (parse_police(&argc
, &argv
, TCA_BPF_POLICE
, n
)) {
155 fprintf(stderr
, "Illegal \"police\"\n");
159 } else if (matches(*argv
, "help") == 0) {
166 fprintf(stderr
, "What is \"%s\"?\n", *argv
);
175 cfg
.ifindex
= t
->tcm_ifindex
;
176 if (bpf_load_common(&cfg
, &bpf_cb_ops
, n
) < 0) {
177 fprintf(stderr
, "Unable to load program\n");
182 addattr32(n
, MAX_MSG
, TCA_BPF_FLAGS_GEN
, bpf_gen_flags
);
184 addattr32(n
, MAX_MSG
, TCA_BPF_FLAGS
, bpf_flags
);
186 tail
->rta_len
= (((void *)n
) + n
->nlmsg_len
) - (void *)tail
;
189 ret
= bpf_send_map_fds(bpf_uds_name
, bpf_obj
);
194 static int bpf_print_opt(struct filter_util
*qu
, FILE *f
,
195 struct rtattr
*opt
, __u32 handle
)
197 struct rtattr
*tb
[TCA_BPF_MAX
+ 1];
203 parse_rtattr_nested(tb
, TCA_BPF_MAX
, opt
);
206 print_0xhex(PRINT_ANY
, "handle", "handle %#llx ", handle
);
208 if (tb
[TCA_BPF_CLASSID
]) {
210 print_string(PRINT_ANY
, "flowid", "flowid %s ",
211 sprint_tc_classid(rta_getattr_u32(tb
[TCA_BPF_CLASSID
]), b1
));
214 if (tb
[TCA_BPF_NAME
])
215 print_string(PRINT_ANY
, "bpf_name", "%s ",
216 rta_getattr_str(tb
[TCA_BPF_NAME
]));
218 if (tb
[TCA_BPF_FLAGS
]) {
219 unsigned int flags
= rta_getattr_u32(tb
[TCA_BPF_FLAGS
]);
221 if (flags
& TCA_BPF_FLAG_ACT_DIRECT
)
222 print_bool(PRINT_ANY
,
223 "direct-action", "direct-action ", true);
226 if (tb
[TCA_BPF_FLAGS_GEN
]) {
228 rta_getattr_u32(tb
[TCA_BPF_FLAGS_GEN
]);
230 if (flags
& TCA_CLS_FLAGS_SKIP_HW
)
231 print_bool(PRINT_ANY
, "skip_hw", "skip_hw ", true);
232 if (flags
& TCA_CLS_FLAGS_SKIP_SW
)
233 print_bool(PRINT_ANY
, "skip_sw", "skip_sw ", true);
234 if (flags
& TCA_CLS_FLAGS_IN_HW
)
235 print_bool(PRINT_ANY
, "in_hw", "in_hw ", true);
236 else if (flags
& TCA_CLS_FLAGS_NOT_IN_HW
)
237 print_bool(PRINT_ANY
,
238 "not_in_hw", "not_in_hw ", true);
241 if (tb
[TCA_BPF_OPS
] && tb
[TCA_BPF_OPS_LEN
])
242 bpf_print_ops(tb
[TCA_BPF_OPS
],
243 rta_getattr_u16(tb
[TCA_BPF_OPS_LEN
]));
246 dump_ok
= bpf_dump_prog_info(f
, rta_getattr_u32(tb
[TCA_BPF_ID
]));
247 if (!dump_ok
&& tb
[TCA_BPF_TAG
]) {
250 print_string(PRINT_ANY
, "tag", "tag %s ",
251 hexstring_n2a(RTA_DATA(tb
[TCA_BPF_TAG
]),
252 RTA_PAYLOAD(tb
[TCA_BPF_TAG
]), b
, sizeof(b
)));
255 if (tb
[TCA_BPF_POLICE
]) {
257 tc_print_police(f
, tb
[TCA_BPF_POLICE
]);
261 tc_print_action(f
, tb
[TCA_BPF_ACT
], 0);
266 struct filter_util bpf_filter_util
= {
268 .parse_fopt
= bpf_parse_opt
,
269 .print_fopt
= bpf_print_opt
,