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 <dborkman@redhat.com>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
24 #include <linux/filter.h>
31 static void explain(void)
33 fprintf(stderr
, "Usage: ... bpf ...\n");
34 fprintf(stderr
, "\n");
35 fprintf(stderr
, " [inline]: run bytecode BPF_BYTECODE\n");
36 fprintf(stderr
, " [from file]: run bytecode-file FILE\n");
37 fprintf(stderr
, " [from file]: run object-file FILE\n");
38 fprintf(stderr
, "\n");
39 fprintf(stderr
, " [ action ACTION_SPEC ]\n");
40 fprintf(stderr
, " [ classid CLASSID ]\n");
41 fprintf(stderr
, "\n");
42 fprintf(stderr
, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
43 fprintf(stderr
, " c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
44 fprintf(stderr
, "Where FILE points to a file containing the BPF_BYTECODE string,\n");
45 fprintf(stderr
, "or an ELF file containing eBPF map definitions and bytecode.\n");
46 fprintf(stderr
, "\nACTION_SPEC := ... look at individual actions\n");
47 fprintf(stderr
, "NOTE: CLASSID is parsed as hexadecimal input.\n");
50 static int bpf_parse_opt(struct filter_util
*qu
, char *handle
,
51 int argc
, char **argv
, struct nlmsghdr
*n
)
53 struct tcmsg
*t
= NLMSG_DATA(n
);
61 h
= strtol(handle
, NULL
, 0);
62 if (h
== LONG_MIN
|| h
== LONG_MAX
) {
63 fprintf(stderr
, "Illegal handle \"%s\", must be "
64 "numeric.\n", handle
);
71 tail
= (struct rtattr
*)(((void*)n
)+NLMSG_ALIGN(n
->nlmsg_len
));
72 addattr_l(n
, MAX_MSG
, TCA_OPTIONS
, NULL
, 0);
75 if (matches(*argv
, "run") == 0) {
76 bool from_file
= true, ebpf
;
77 struct sock_filter bpf_ops
[BPF_MAXINSNS
];
81 if (strcmp(*argv
, "bytecode-file") == 0) {
83 } else if (strcmp(*argv
, "bytecode") == 0) {
86 } else if (strcmp(*argv
, "object-file") == 0) {
89 fprintf(stderr
, "What is \"%s\"?\n", *argv
);
94 ret
= ebpf
? bpf_open_object(*argv
, BPF_PROG_TYPE_SCHED_CLS
) :
95 bpf_parse_ops(argc
, argv
, bpf_ops
, from_file
);
97 fprintf(stderr
, "%s\n", ebpf
?
98 "Could not load object" :
99 "Illegal \"bytecode\"");
103 addattr32(n
, MAX_MSG
, TCA_BPF_FD
, ret
);
104 addattrstrz(n
, MAX_MSG
, TCA_BPF_NAME
, *argv
);
106 addattr16(n
, MAX_MSG
, TCA_BPF_OPS_LEN
, ret
);
107 addattr_l(n
, MAX_MSG
, TCA_BPF_OPS
, &bpf_ops
,
108 ret
* sizeof(struct sock_filter
));
110 } else if (matches(*argv
, "classid") == 0 ||
111 strcmp(*argv
, "flowid") == 0) {
114 if (get_tc_classid(&handle
, *argv
)) {
115 fprintf(stderr
, "Illegal \"classid\"\n");
118 addattr_l(n
, MAX_MSG
, TCA_BPF_CLASSID
, &handle
, 4);
119 } else if (matches(*argv
, "action") == 0) {
121 if (parse_action(&argc
, &argv
, TCA_BPF_ACT
, n
)) {
122 fprintf(stderr
, "Illegal \"action\"\n");
126 } else if (matches(*argv
, "police") == 0) {
128 if (parse_police(&argc
, &argv
, TCA_BPF_POLICE
, n
)) {
129 fprintf(stderr
, "Illegal \"police\"\n");
133 } else if (strcmp(*argv
, "help") == 0) {
137 fprintf(stderr
, "What is \"%s\"?\n", *argv
);
144 tail
->rta_len
= (((void*)n
)+n
->nlmsg_len
) - (void*)tail
;
148 static int bpf_print_opt(struct filter_util
*qu
, FILE *f
,
149 struct rtattr
*opt
, __u32 handle
)
151 struct rtattr
*tb
[TCA_BPF_MAX
+ 1];
156 parse_rtattr_nested(tb
, TCA_BPF_MAX
, opt
);
159 fprintf(f
, "handle 0x%x ", handle
);
161 if (tb
[TCA_BPF_CLASSID
]) {
163 fprintf(f
, "flowid %s ",
164 sprint_tc_classid(rta_getattr_u32(tb
[TCA_BPF_CLASSID
]), b1
));
167 if (tb
[TCA_BPF_NAME
])
168 fprintf(f
, "%s ", rta_getattr_str(tb
[TCA_BPF_NAME
]));
169 else if (tb
[TCA_BPF_FD
])
170 fprintf(f
, "pfd %u ", rta_getattr_u32(tb
[TCA_BPF_FD
]));
172 if (tb
[TCA_BPF_OPS
] && tb
[TCA_BPF_OPS_LEN
])
173 bpf_print_ops(f
, tb
[TCA_BPF_OPS
],
174 rta_getattr_u16(tb
[TCA_BPF_OPS_LEN
]));
176 if (tb
[TCA_BPF_POLICE
]) {
178 tc_print_police(f
, tb
[TCA_BPF_POLICE
]);
181 if (tb
[TCA_BPF_ACT
]) {
182 tc_print_action(f
, tb
[TCA_BPF_ACT
]);
188 struct filter_util bpf_filter_util
= {
190 .parse_fopt
= bpf_parse_opt
,
191 .print_fopt
= bpf_print_opt
,