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)
94 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
97 if (matches(*argv
, "run") == 0) {
104 if (bpf_parse_common(bpf_type
, &cfg
, &bpf_cb_ops
, n
))
110 bpf_obj
= cfg
.object
;
111 bpf_uds_name
= cfg
.uds
;
112 } else if (matches(*argv
, "help") == 0) {
115 } else if (matches(*argv
, "index") == 0) {
126 parse_action_control_dflt(&argc
, &argv
, &parm
.action
,
130 if (matches(*argv
, "index") == 0) {
132 if (get_u32(&parm
.index
, *argv
, 10)) {
133 fprintf(stderr
, "bpf: Illegal \"index\"\n");
141 addattr_l(n
, MAX_MSG
, TCA_ACT_BPF_PARMS
, &parm
, sizeof(parm
));
142 tail
->rta_len
= (char *)NLMSG_TAIL(n
) - (char *)tail
;
145 ret
= bpf_send_map_fds(bpf_uds_name
, bpf_obj
);
153 static int bpf_print_opt(struct action_util
*au
, FILE *f
, struct rtattr
*arg
)
155 struct rtattr
*tb
[TCA_ACT_BPF_MAX
+ 1];
156 struct tc_act_bpf
*parm
;
162 parse_rtattr_nested(tb
, TCA_ACT_BPF_MAX
, arg
);
164 if (!tb
[TCA_ACT_BPF_PARMS
]) {
165 fprintf(f
, "[NULL bpf parameters]");
169 parm
= RTA_DATA(tb
[TCA_ACT_BPF_PARMS
]);
172 if (tb
[TCA_ACT_BPF_NAME
])
173 fprintf(f
, "%s ", rta_getattr_str(tb
[TCA_ACT_BPF_NAME
]));
175 if (tb
[TCA_ACT_BPF_OPS
] && tb
[TCA_ACT_BPF_OPS_LEN
]) {
176 bpf_print_ops(f
, tb
[TCA_ACT_BPF_OPS
],
177 rta_getattr_u16(tb
[TCA_ACT_BPF_OPS_LEN
]));
181 if (tb
[TCA_ACT_BPF_ID
])
182 dump_ok
= bpf_dump_prog_info(f
, rta_getattr_u32(tb
[TCA_ACT_BPF_ID
]));
183 if (!dump_ok
&& tb
[TCA_ACT_BPF_TAG
]) {
186 fprintf(f
, "tag %s ",
187 hexstring_n2a(RTA_DATA(tb
[TCA_ACT_BPF_TAG
]),
188 RTA_PAYLOAD(tb
[TCA_ACT_BPF_TAG
]),
192 print_action_control(f
, "default-action ", parm
->action
, "\n");
193 fprintf(f
, "\tindex %u ref %d bind %d", parm
->index
, parm
->refcnt
,
197 if (tb
[TCA_ACT_BPF_TM
]) {
198 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_ACT_BPF_TM
]);
208 struct action_util bpf_action_util
= {
210 .parse_aopt
= bpf_parse_opt
,
211 .print_aopt
= bpf_print_opt
,