2 * m_bpf.c BPF based action module
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.
9 * Authors: Jiri Pirko <jiri@resnulli.us>
10 * Daniel Borkmann <daniel@iogearbox.net>
16 #include <linux/bpf.h>
17 #include <linux/tc_act/tc_bpf.h>
24 static const enum bpf_prog_type bpf_type
= BPF_PROG_TYPE_SCHED_ACT
;
26 static void explain(void)
28 fprintf(stderr
, "Usage: ... bpf ... [ index INDEX ]\n");
29 fprintf(stderr
, "\n");
30 fprintf(stderr
, "BPF use case:\n");
31 fprintf(stderr
, " bytecode BPF_BYTECODE\n");
32 fprintf(stderr
, " bytecode-file FILE\n");
33 fprintf(stderr
, "\n");
34 fprintf(stderr
, "eBPF use case:\n");
35 fprintf(stderr
, " object-file FILE [ section ACT_NAME ] [ export UDS_FILE ]");
36 fprintf(stderr
, " [ verbose ]\n");
37 fprintf(stderr
, " object-pinned FILE\n");
38 fprintf(stderr
, "\n");
39 fprintf(stderr
, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
40 fprintf(stderr
, "c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
41 fprintf(stderr
, "\n");
42 fprintf(stderr
, "Where FILE points to a file containing the BPF_BYTECODE string,\n");
43 fprintf(stderr
, "an ELF file containing eBPF map definitions and bytecode, or a\n");
44 fprintf(stderr
, "pinned eBPF program.\n");
45 fprintf(stderr
, "\n");
46 fprintf(stderr
, "Where ACT_NAME refers to the section name containing the\n");
47 fprintf(stderr
, "action (default \'%s\').\n", bpf_prog_to_default_section(bpf_type
));
48 fprintf(stderr
, "\n");
49 fprintf(stderr
, "Where UDS_FILE points to a unix domain socket file in order\n");
50 fprintf(stderr
, "to hand off control of all created eBPF maps to an agent.\n");
51 fprintf(stderr
, "\n");
52 fprintf(stderr
, "Where optionally INDEX points to an existing action, or\n");
53 fprintf(stderr
, "explicitly specifies an action index upon creation.\n");
56 static void bpf_cbpf_cb(void *nl
, const struct sock_filter
*ops
, int ops_len
)
58 addattr16(nl
, MAX_MSG
, TCA_ACT_BPF_OPS_LEN
, ops_len
);
59 addattr_l(nl
, MAX_MSG
, TCA_ACT_BPF_OPS
, ops
,
60 ops_len
* sizeof(struct sock_filter
));
63 static void bpf_ebpf_cb(void *nl
, int fd
, const char *annotation
)
65 addattr32(nl
, MAX_MSG
, TCA_ACT_BPF_FD
, fd
);
66 addattrstrz(nl
, MAX_MSG
, TCA_ACT_BPF_NAME
, annotation
);
69 static const struct bpf_cfg_ops bpf_cb_ops
= {
70 .cbpf_cb
= bpf_cbpf_cb
,
71 .ebpf_cb
= bpf_ebpf_cb
,
74 static int bpf_parse_opt(struct action_util
*a
, int *ptr_argc
, char ***ptr_argv
,
75 int tca_id
, struct nlmsghdr
*n
)
77 const char *bpf_obj
= NULL
, *bpf_uds_name
= NULL
;
78 struct tc_act_bpf parm
= {};
79 struct bpf_cfg_in cfg
= {};
80 bool seen_run
= false;
88 if (matches(*argv
, "bpf") != 0)
93 tail
= addattr_nest(n
, MAX_MSG
, tca_id
);
96 if (matches(*argv
, "run") == 0) {
100 duparg("run", *argv
);
107 if (bpf_parse_and_load_common(&cfg
, &bpf_cb_ops
, n
))
113 bpf_obj
= cfg
.object
;
114 bpf_uds_name
= cfg
.uds
;
115 } else if (matches(*argv
, "help") == 0) {
118 } else if (matches(*argv
, "index") == 0) {
129 parse_action_control_dflt(&argc
, &argv
, &parm
.action
,
133 if (matches(*argv
, "index") == 0) {
135 if (get_u32(&parm
.index
, *argv
, 10)) {
136 fprintf(stderr
, "bpf: Illegal \"index\"\n");
144 addattr_l(n
, MAX_MSG
, TCA_ACT_BPF_PARMS
, &parm
, sizeof(parm
));
145 addattr_nest_end(n
, tail
);
148 ret
= bpf_send_map_fds(bpf_uds_name
, bpf_obj
);
156 static int bpf_print_opt(struct action_util
*au
, FILE *f
, struct rtattr
*arg
)
158 struct rtattr
*tb
[TCA_ACT_BPF_MAX
+ 1];
159 struct tc_act_bpf
*parm
;
165 parse_rtattr_nested(tb
, TCA_ACT_BPF_MAX
, arg
);
167 if (!tb
[TCA_ACT_BPF_PARMS
]) {
168 fprintf(f
, "[NULL bpf parameters]");
172 parm
= RTA_DATA(tb
[TCA_ACT_BPF_PARMS
]);
175 if (tb
[TCA_ACT_BPF_NAME
])
176 fprintf(f
, "%s ", rta_getattr_str(tb
[TCA_ACT_BPF_NAME
]));
178 if (tb
[TCA_ACT_BPF_OPS
] && tb
[TCA_ACT_BPF_OPS_LEN
]) {
179 bpf_print_ops(f
, tb
[TCA_ACT_BPF_OPS
],
180 rta_getattr_u16(tb
[TCA_ACT_BPF_OPS_LEN
]));
184 if (tb
[TCA_ACT_BPF_ID
])
185 dump_ok
= bpf_dump_prog_info(f
, rta_getattr_u32(tb
[TCA_ACT_BPF_ID
]));
186 if (!dump_ok
&& tb
[TCA_ACT_BPF_TAG
]) {
189 fprintf(f
, "tag %s ",
190 hexstring_n2a(RTA_DATA(tb
[TCA_ACT_BPF_TAG
]),
191 RTA_PAYLOAD(tb
[TCA_ACT_BPF_TAG
]),
195 print_action_control(f
, "default-action ", parm
->action
, "\n");
196 fprintf(f
, "\tindex %u ref %d bind %d", parm
->index
, parm
->refcnt
,
200 if (tb
[TCA_ACT_BPF_TM
]) {
201 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_ACT_BPF_TM
]);
211 struct action_util bpf_action_util
= {
213 .parse_aopt
= bpf_parse_opt
,
214 .print_aopt
= bpf_print_opt
,