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>
23 static const enum bpf_prog_type bpf_type
= BPF_PROG_TYPE_SCHED_ACT
;
25 static const int nla_tbl
[BPF_NLA_MAX
] = {
26 [BPF_NLA_OPS_LEN
] = TCA_ACT_BPF_OPS_LEN
,
27 [BPF_NLA_OPS
] = TCA_ACT_BPF_OPS
,
28 [BPF_NLA_FD
] = TCA_ACT_BPF_FD
,
29 [BPF_NLA_NAME
] = TCA_ACT_BPF_NAME
,
32 static void explain(void)
34 fprintf(stderr
, "Usage: ... bpf ... [ index INDEX ]\n");
35 fprintf(stderr
, "\n");
36 fprintf(stderr
, "BPF use case:\n");
37 fprintf(stderr
, " bytecode BPF_BYTECODE\n");
38 fprintf(stderr
, " bytecode-file FILE\n");
39 fprintf(stderr
, "\n");
40 fprintf(stderr
, "eBPF use case:\n");
41 fprintf(stderr
, " object-file FILE [ section ACT_NAME ] [ export UDS_FILE ]");
42 fprintf(stderr
, " [ verbose ]\n");
43 fprintf(stderr
, " object-pinned FILE\n");
44 fprintf(stderr
, "\n");
45 fprintf(stderr
, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
46 fprintf(stderr
, "c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
47 fprintf(stderr
, "\n");
48 fprintf(stderr
, "Where FILE points to a file containing the BPF_BYTECODE string,\n");
49 fprintf(stderr
, "an ELF file containing eBPF map definitions and bytecode, or a\n");
50 fprintf(stderr
, "pinned eBPF program.\n");
51 fprintf(stderr
, "\n");
52 fprintf(stderr
, "Where ACT_NAME refers to the section name containing the\n");
53 fprintf(stderr
, "action (default \'%s\').\n", bpf_default_section(bpf_type
));
54 fprintf(stderr
, "\n");
55 fprintf(stderr
, "Where UDS_FILE points to a unix domain socket file in order\n");
56 fprintf(stderr
, "to hand off control of all created eBPF maps to an agent.\n");
57 fprintf(stderr
, "\n");
58 fprintf(stderr
, "Where optionally INDEX points to an existing action, or\n");
59 fprintf(stderr
, "explicitly specifies an action index upon creation.\n");
62 static int bpf_parse_opt(struct action_util
*a
, int *ptr_argc
, char ***ptr_argv
,
63 int tca_id
, struct nlmsghdr
*n
)
65 const char *bpf_obj
= NULL
, *bpf_uds_name
= NULL
;
66 struct tc_act_bpf parm
;
67 bool seen_run
= false;
75 if (matches(*argv
, "bpf") != 0)
81 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
84 if (matches(*argv
, "run") == 0) {
88 if (bpf_parse_common(&argc
, &argv
, nla_tbl
, bpf_type
,
89 &bpf_obj
, &bpf_uds_name
, n
)) {
90 fprintf(stderr
, "Failed to retrieve (e)BPF data!\n");
93 } else if (matches(*argv
, "help") == 0) {
96 } else if (matches(*argv
, "index") == 0) {
107 memset(&parm
, 0, sizeof(parm
));
108 parm
.action
= TC_ACT_PIPE
;
111 if (matches(*argv
, "reclassify") == 0) {
112 parm
.action
= TC_ACT_RECLASSIFY
;
114 } else if (matches(*argv
, "pipe") == 0) {
115 parm
.action
= TC_ACT_PIPE
;
117 } else if (matches(*argv
, "drop") == 0 ||
118 matches(*argv
, "shot") == 0) {
119 parm
.action
= TC_ACT_SHOT
;
121 } else if (matches(*argv
, "continue") == 0) {
122 parm
.action
= TC_ACT_UNSPEC
;
124 } else if (matches(*argv
, "pass") == 0 ||
125 matches(*argv
, "ok") == 0) {
126 parm
.action
= TC_ACT_OK
;
132 if (matches(*argv
, "index") == 0) {
134 if (get_u32(&parm
.index
, *argv
, 10)) {
135 fprintf(stderr
, "bpf: Illegal \"index\"\n");
143 addattr_l(n
, MAX_MSG
, TCA_ACT_BPF_PARMS
, &parm
, sizeof(parm
));
144 tail
->rta_len
= (char *)NLMSG_TAIL(n
) - (char *)tail
;
147 ret
= bpf_send_map_fds(bpf_uds_name
, bpf_obj
);
155 static int bpf_print_opt(struct action_util
*au
, FILE *f
, struct rtattr
*arg
)
157 struct rtattr
*tb
[TCA_ACT_BPF_MAX
+ 1];
158 struct tc_act_bpf
*parm
;
159 SPRINT_BUF(action_buf
);
164 parse_rtattr_nested(tb
, TCA_ACT_BPF_MAX
, arg
);
166 if (!tb
[TCA_ACT_BPF_PARMS
]) {
167 fprintf(f
, "[NULL bpf parameters]");
171 parm
= RTA_DATA(tb
[TCA_ACT_BPF_PARMS
]);
174 if (tb
[TCA_ACT_BPF_NAME
])
175 fprintf(f
, "%s ", rta_getattr_str(tb
[TCA_ACT_BPF_NAME
]));
176 else if (tb
[TCA_ACT_BPF_FD
])
177 fprintf(f
, "pfd %u ", rta_getattr_u32(tb
[TCA_ACT_BPF_FD
]));
179 if (tb
[TCA_ACT_BPF_OPS
] && tb
[TCA_ACT_BPF_OPS_LEN
]) {
180 bpf_print_ops(f
, tb
[TCA_ACT_BPF_OPS
],
181 rta_getattr_u16(tb
[TCA_ACT_BPF_OPS_LEN
]));
185 fprintf(f
, "default-action %s\n", action_n2a(parm
->action
, action_buf
,
186 sizeof(action_buf
)));
187 fprintf(f
, "\tindex %d ref %d bind %d", parm
->index
, parm
->refcnt
,
191 if (tb
[TCA_ACT_BPF_TM
]) {
192 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_ACT_BPF_TM
]);
201 struct action_util bpf_action_util
= {
203 .parse_aopt
= bpf_parse_opt
,
204 .print_aopt
= bpf_print_opt
,