2 * Berkeley Packet Filter based traffic classifier
4 * Might be used to classify traffic through flexible, user-defined and
5 * possibly JIT-ed BPF filters for traffic control as an alternative to
8 * (C) 2013 Daniel Borkmann <dborkman@redhat.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/skbuff.h>
18 #include <linux/filter.h>
19 #include <net/rtnetlink.h>
20 #include <net/pkt_cls.h>
23 MODULE_LICENSE("GPL");
24 MODULE_AUTHOR("Daniel Borkmann <dborkman@redhat.com>");
25 MODULE_DESCRIPTION("TC BPF based classifier");
28 struct list_head plist
;
34 struct bpf_prog
*filter
;
35 struct sock_filter
*bpf_ops
;
37 struct tcf_result res
;
38 struct list_head link
;
45 static const struct nla_policy bpf_policy
[TCA_BPF_MAX
+ 1] = {
46 [TCA_BPF_CLASSID
] = { .type
= NLA_U32
},
47 [TCA_BPF_OPS_LEN
] = { .type
= NLA_U16
},
48 [TCA_BPF_OPS
] = { .type
= NLA_BINARY
,
49 .len
= sizeof(struct sock_filter
) * BPF_MAXINSNS
},
52 static int cls_bpf_classify(struct sk_buff
*skb
, const struct tcf_proto
*tp
,
53 struct tcf_result
*res
)
55 struct cls_bpf_head
*head
= rcu_dereference_bh(tp
->root
);
56 struct cls_bpf_prog
*prog
;
59 list_for_each_entry_rcu(prog
, &head
->plist
, link
) {
60 int filter_res
= BPF_PROG_RUN(prog
->filter
, skb
);
67 res
->classid
= filter_res
;
69 ret
= tcf_exts_exec(skb
, &prog
->exts
, res
);
79 static int cls_bpf_init(struct tcf_proto
*tp
)
81 struct cls_bpf_head
*head
;
83 head
= kzalloc(sizeof(*head
), GFP_KERNEL
);
87 INIT_LIST_HEAD_RCU(&head
->plist
);
88 rcu_assign_pointer(tp
->root
, head
);
93 static void cls_bpf_delete_prog(struct tcf_proto
*tp
, struct cls_bpf_prog
*prog
)
95 tcf_exts_destroy(&prog
->exts
);
97 bpf_prog_destroy(prog
->filter
);
103 static void __cls_bpf_delete_prog(struct rcu_head
*rcu
)
105 struct cls_bpf_prog
*prog
= container_of(rcu
, struct cls_bpf_prog
, rcu
);
107 cls_bpf_delete_prog(prog
->tp
, prog
);
110 static int cls_bpf_delete(struct tcf_proto
*tp
, unsigned long arg
)
112 struct cls_bpf_head
*head
= rtnl_dereference(tp
->root
);
113 struct cls_bpf_prog
*prog
, *todel
= (struct cls_bpf_prog
*) arg
;
115 list_for_each_entry(prog
, &head
->plist
, link
) {
117 list_del_rcu(&prog
->link
);
118 tcf_unbind_filter(tp
, &prog
->res
);
119 call_rcu(&prog
->rcu
, __cls_bpf_delete_prog
);
127 static void cls_bpf_destroy(struct tcf_proto
*tp
)
129 struct cls_bpf_head
*head
= rtnl_dereference(tp
->root
);
130 struct cls_bpf_prog
*prog
, *tmp
;
132 list_for_each_entry_safe(prog
, tmp
, &head
->plist
, link
) {
133 list_del_rcu(&prog
->link
);
134 tcf_unbind_filter(tp
, &prog
->res
);
135 call_rcu(&prog
->rcu
, __cls_bpf_delete_prog
);
138 RCU_INIT_POINTER(tp
->root
, NULL
);
139 kfree_rcu(head
, rcu
);
142 static unsigned long cls_bpf_get(struct tcf_proto
*tp
, u32 handle
)
144 struct cls_bpf_head
*head
= rtnl_dereference(tp
->root
);
145 struct cls_bpf_prog
*prog
;
146 unsigned long ret
= 0UL;
151 list_for_each_entry_rcu(prog
, &head
->plist
, link
) {
152 if (prog
->handle
== handle
) {
153 ret
= (unsigned long) prog
;
161 static void cls_bpf_put(struct tcf_proto
*tp
, unsigned long f
)
165 static int cls_bpf_modify_existing(struct net
*net
, struct tcf_proto
*tp
,
166 struct cls_bpf_prog
*prog
,
167 unsigned long base
, struct nlattr
**tb
,
168 struct nlattr
*est
, bool ovr
)
170 struct sock_filter
*bpf_ops
;
171 struct tcf_exts exts
;
172 struct sock_fprog_kern tmp
;
174 u16 bpf_size
, bpf_len
;
178 if (!tb
[TCA_BPF_OPS_LEN
] || !tb
[TCA_BPF_OPS
] || !tb
[TCA_BPF_CLASSID
])
181 tcf_exts_init(&exts
, TCA_BPF_ACT
, TCA_BPF_POLICE
);
182 ret
= tcf_exts_validate(net
, tp
, tb
, est
, &exts
, ovr
);
186 classid
= nla_get_u32(tb
[TCA_BPF_CLASSID
]);
187 bpf_len
= nla_get_u16(tb
[TCA_BPF_OPS_LEN
]);
188 if (bpf_len
> BPF_MAXINSNS
|| bpf_len
== 0) {
193 bpf_size
= bpf_len
* sizeof(*bpf_ops
);
194 bpf_ops
= kzalloc(bpf_size
, GFP_KERNEL
);
195 if (bpf_ops
== NULL
) {
200 memcpy(bpf_ops
, nla_data(tb
[TCA_BPF_OPS
]), bpf_size
);
203 tmp
.filter
= bpf_ops
;
205 ret
= bpf_prog_create(&fp
, &tmp
);
209 prog
->bpf_len
= bpf_len
;
210 prog
->bpf_ops
= bpf_ops
;
212 prog
->res
.classid
= classid
;
214 tcf_bind_filter(tp
, &prog
->res
, base
);
215 tcf_exts_change(tp
, &prog
->exts
, &exts
);
221 tcf_exts_destroy(&exts
);
225 static u32
cls_bpf_grab_new_handle(struct tcf_proto
*tp
,
226 struct cls_bpf_head
*head
)
228 unsigned int i
= 0x80000000;
231 if (++head
->hgen
== 0x7FFFFFFF)
233 } while (--i
> 0 && cls_bpf_get(tp
, head
->hgen
));
235 pr_err("Insufficient number of handles\n");
240 static int cls_bpf_change(struct net
*net
, struct sk_buff
*in_skb
,
241 struct tcf_proto
*tp
, unsigned long base
,
242 u32 handle
, struct nlattr
**tca
,
243 unsigned long *arg
, bool ovr
)
245 struct cls_bpf_head
*head
= rtnl_dereference(tp
->root
);
246 struct cls_bpf_prog
*oldprog
= (struct cls_bpf_prog
*) *arg
;
247 struct nlattr
*tb
[TCA_BPF_MAX
+ 1];
248 struct cls_bpf_prog
*prog
;
251 if (tca
[TCA_OPTIONS
] == NULL
)
254 ret
= nla_parse_nested(tb
, TCA_BPF_MAX
, tca
[TCA_OPTIONS
], bpf_policy
);
258 prog
= kzalloc(sizeof(*prog
), GFP_KERNEL
);
262 tcf_exts_init(&prog
->exts
, TCA_BPF_ACT
, TCA_BPF_POLICE
);
265 if (handle
&& oldprog
->handle
!= handle
) {
272 prog
->handle
= cls_bpf_grab_new_handle(tp
, head
);
274 prog
->handle
= handle
;
275 if (prog
->handle
== 0) {
280 ret
= cls_bpf_modify_existing(net
, tp
, prog
, base
, tb
, tca
[TCA_RATE
], ovr
);
285 list_replace_rcu(&prog
->link
, &oldprog
->link
);
286 tcf_unbind_filter(tp
, &oldprog
->res
);
287 call_rcu(&oldprog
->rcu
, __cls_bpf_delete_prog
);
289 list_add_rcu(&prog
->link
, &head
->plist
);
292 *arg
= (unsigned long) prog
;
300 static int cls_bpf_dump(struct net
*net
, struct tcf_proto
*tp
, unsigned long fh
,
301 struct sk_buff
*skb
, struct tcmsg
*tm
)
303 struct cls_bpf_prog
*prog
= (struct cls_bpf_prog
*) fh
;
304 struct nlattr
*nest
, *nla
;
309 tm
->tcm_handle
= prog
->handle
;
311 nest
= nla_nest_start(skb
, TCA_OPTIONS
);
313 goto nla_put_failure
;
315 if (nla_put_u32(skb
, TCA_BPF_CLASSID
, prog
->res
.classid
))
316 goto nla_put_failure
;
317 if (nla_put_u16(skb
, TCA_BPF_OPS_LEN
, prog
->bpf_len
))
318 goto nla_put_failure
;
320 nla
= nla_reserve(skb
, TCA_BPF_OPS
, prog
->bpf_len
*
321 sizeof(struct sock_filter
));
323 goto nla_put_failure
;
325 memcpy(nla_data(nla
), prog
->bpf_ops
, nla_len(nla
));
327 if (tcf_exts_dump(skb
, &prog
->exts
) < 0)
328 goto nla_put_failure
;
330 nla_nest_end(skb
, nest
);
332 if (tcf_exts_dump_stats(skb
, &prog
->exts
) < 0)
333 goto nla_put_failure
;
338 nla_nest_cancel(skb
, nest
);
342 static void cls_bpf_walk(struct tcf_proto
*tp
, struct tcf_walker
*arg
)
344 struct cls_bpf_head
*head
= rtnl_dereference(tp
->root
);
345 struct cls_bpf_prog
*prog
;
347 list_for_each_entry_rcu(prog
, &head
->plist
, link
) {
348 if (arg
->count
< arg
->skip
)
350 if (arg
->fn(tp
, (unsigned long) prog
, arg
) < 0) {
359 static struct tcf_proto_ops cls_bpf_ops __read_mostly
= {
361 .owner
= THIS_MODULE
,
362 .classify
= cls_bpf_classify
,
363 .init
= cls_bpf_init
,
364 .destroy
= cls_bpf_destroy
,
367 .change
= cls_bpf_change
,
368 .delete = cls_bpf_delete
,
369 .walk
= cls_bpf_walk
,
370 .dump
= cls_bpf_dump
,
373 static int __init
cls_bpf_init_mod(void)
375 return register_tcf_proto_ops(&cls_bpf_ops
);
378 static void __exit
cls_bpf_exit_mod(void)
380 unregister_tcf_proto_ops(&cls_bpf_ops
);
383 module_init(cls_bpf_init_mod
);
384 module_exit(cls_bpf_exit_mod
);