2 * cls_canprio.c -- Canprio classifier.
3 * Makes decisions accoring to controller area network (CAN) identifiers.
5 * This program is free software; you can distribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; version 2 of
10 * Idea: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
11 * Copyright: (c) 2011 Czech Technical University in Prague
12 * (c) 2011 Volkswagen Group Research
13 * Authors: Michal Sojka <sojkam1@fel.cvut.cz>
14 * Pavel Pisa <pisa@cmp.felk.cvut.cz>
15 * Rostislav Lisovy <lisovy@kormus.cz>
16 * Founded by: Volkswagen Group Research
18 * Some function descriptions are heavily inspired by article "Linux Network
19 * Traffic Control -- Implementation Overview" by Werner Almesberger
22 * Implementation notes;
23 * parameter of functions named "base" is pointer to some parent element
26 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <linux/types.h>
29 #include <linux/kernel.h>
30 #include <linux/string.h>
31 #include <linux/errno.h>
32 #include <linux/rtnetlink.h>
33 #include <linux/skbuff.h>
34 #include <net/netlink.h>
35 #include <net/act_api.h>
36 #include <net/pkt_cls.h>
37 #include <linux/bitmap.h>
38 #include <linux/spinlock.h>
39 #include <linux/rcupdate.h>
40 #include <linux/can.h>
42 #ifndef CAN_SFF_ID_BITS
43 #define CAN_SFF_ID_BITS 11
44 #define CAN_EFF_ID_BITS 29
50 /* Definition of Netlink messages */
54 TCA_CANPRIO_RULES, /* Array of can_filter structs; We are able
55 to determine the length after receiving */
56 TCA_CANPRIO_INV_EN, /* enable inverse rules */
59 #define TCA_CANPRIO_MAX (__TCA_CANPRIO_MAX - 1)
61 static const struct nla_policy canprio_policy[TCA_CANPRIO_MAX + 1] = {
62 [TCA_CANPRIO_CLASSID] = { .type = NLA_U32 },
63 //FIXME Be aware of possible problems with 64bit kernel and 32bit userspace etc.
64 [TCA_CANPRIO_RULES] = { /*.len = (sizeof(struct can_filter))*/ }, //FIXME
65 [TCA_CANPRIO_INV_EN] = { .type = NLA_U32 },
68 struct canprio_rules {
69 struct can_filter *rules_raw; /* Raw rules copied from netlink message;
70 Used for sending information to userspace
71 (when 'tc filter show' is invoked) AND
72 when matching EFF frames*/
74 DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS)); /* For each SFF Can ID (11 bit)
75 there is one record in this bitfield */
77 int inv_match_en; /* Inverted match flag */
87 struct list_head flist;
90 struct canprio_filter {
92 struct canprio_rules *rules; /* All rules necessary for classification */
93 struct tcf_result res; /* Class ID (flow id) the instance
94 of a filter is bound to */
95 struct list_head link;
99 * ----------------------------------------------------------------------------
103 static void canprio_sff_match_add(struct canprio_rules *rls, u32 can_id, u32 can_mask)
107 pr_debug("%s() invoked\n", __FUNCTION__);
108 /* Limit can_mask and can_id to SFF range to protect against write after end of array */
109 can_mask &= CAN_SFF_MASK;
113 if (can_mask == CAN_SFF_MASK) {
114 set_bit(can_id, rls->match_sff);
120 bitmap_fill(rls->match_sff, (1 << CAN_SFF_ID_BITS));
124 /* individual frame filter */
125 /* Add record (set bit to 1) for each ID that conforms particular rule */
126 for (i = 0; i < (1 << CAN_SFF_ID_BITS); i++) {
127 if ((i & can_mask) == can_id)
128 set_bit(i, rls->match_sff);
134 * Extracts Can ID ot ouf the sk_buff structure.
136 static canid_t canprio_get_id(struct sk_buff *skb)
138 /* Can ID is inside of data field */
139 struct can_frame *cf = (struct can_frame *)skb->data;
145 * Performs the classification. Iterates over all instances of filter
146 * checking for Can ID match.
148 * @skb: Socket buffer
150 * @res: Is used for setting Class ID as a result of classification
152 * Returns value relevant for policing. Used return values:
153 * TC_POLICE_OK if succesfully classified (without regard to policing rules)
154 * TC_POLICE_UNSPEC if no matching filter was found
156 static int canprio_classify(struct sk_buff *skb, struct tcf_proto *tp,
157 struct tcf_result *res)
159 struct canprio_head *head = (struct canprio_head *)tp->root;
160 struct canprio_filter *f;
161 struct canprio_rules *r;
165 pr_debug(" canprio_classify() invoked\n");
166 can_id = (u32)canprio_get_id(skb);
169 list_for_each_entry(f, &head->flist, link) {
171 r = rcu_dereference(f->rules);
174 if (can_id & CAN_EFF_FLAG) {
175 can_id &= CAN_EFF_MASK;
177 for (i = 0; i < r->eff_rules_count; i++) {
178 if ((r->rules_raw[i].can_id & r->rules_raw[i].can_mask & CAN_EFF_MASK) ==
179 (can_id & r->rules_raw[i].can_mask & CAN_EFF_MASK)) {
186 can_id &= CAN_SFF_MASK;
188 match = test_bit(can_id, r->match_sff);
190 for (i = r->eff_rules_count; i < r->eff_rules_count + r->sff_rules_count; i++) {
191 if ((r->rules_raw[i].can_id & r->rules_raw[i].can_mask & CAN_SFF_MASK) ==
192 (can_id & r->rules_raw[i].can_mask & CAN_SFF_MASK)) {
201 //if (r->inv_match_en)
206 pr_debug( " canprio_classify() match ok: ID 0x%x\n", can_id);
213 return TC_POLICE_UNSPEC;
217 * Looks up a filter element by its handle and returns the internal
218 * filter ID (i.e. pointer)
220 static unsigned long canprio_get(struct tcf_proto *tp, u32 handle)
222 struct canprio_head *head = (struct canprio_head *)tp->root;
223 struct canprio_filter *f;
228 list_for_each_entry(f, &head->flist, link) {
229 if (f->handle == handle) {
230 return (unsigned long) f;
238 * Is invoked when a filter element previously referenced
239 * with get() is no longer used
241 static void canprio_put(struct tcf_proto *tp, unsigned long f)
246 static unsigned int canprio_gen_handle(struct tcf_proto *tp)
248 struct canprio_head *head = (struct canprio_head *)tp->root;
254 if ((head->hgenerator += 0x10000) == 0)
255 head->hgenerator = 0x10000;
257 h = head->hgenerator;
258 if (canprio_get(tp, h) == 0);
265 static void canprio_rules_free_rcu(struct rcu_head *rcu)
267 kfree(container_of(rcu, struct canprio_rules, rcu));
270 static int canprio_set_parms(struct tcf_proto *tp, struct canprio_filter *f,
271 unsigned long base, struct nlattr **tb,
274 struct can_filter *canprio_nl_rules;
275 struct canprio_rules *rules_tmp;
278 pr_debug("%s() invoked\n", __FUNCTION__);
280 rules_tmp = kzalloc(sizeof(*rules_tmp), GFP_KERNEL);
281 if (rules_tmp == NULL)
285 if (tb[TCA_CANPRIO_CLASSID] == NULL)
288 if (tb[TCA_CANPRIO_RULES]) {
289 canprio_nl_rules = nla_data(tb[TCA_CANPRIO_RULES]);
290 rules_tmp->sff_rules_count = 0;
291 rules_tmp->eff_rules_count = 0;
292 rules_tmp->rules_count = (nla_len(tb[TCA_CANPRIO_RULES]) / sizeof(struct can_filter));
293 pr_debug(" rules_count = %u\n", rules_tmp->rules_count);
295 rules_tmp->rules_raw = kzalloc(sizeof(struct can_filter) * rules_tmp->rules_count, GFP_KERNEL);
297 if (rules_tmp->rules_raw == NULL)
300 /* Process EFF frames */
301 for (i = 0; i < rules_tmp->rules_count; i++) {
302 if ((canprio_nl_rules[i].can_id & CAN_EFF_FLAG) &&
303 (canprio_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
305 memcpy(rules_tmp->rules_raw + rules_tmp->eff_rules_count,
306 &canprio_nl_rules[i], sizeof(struct can_filter));
307 rules_tmp->eff_rules_count ++;
309 pr_debug(" can ID to match = 0x%x with mask 0x%x\n",
310 canprio_nl_rules[i].can_id, canprio_nl_rules[i].can_mask);
316 /* Process SFF frames
317 We need two for() loops for copying rules into two contiguous areas in rules_raw */
318 for (i = 0; i < rules_tmp->rules_count; i++) {
319 if ((canprio_nl_rules[i].can_id & CAN_EFF_FLAG) &&
320 (canprio_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
324 memcpy(rules_tmp->rules_raw + rules_tmp->eff_rules_count + rules_tmp->sff_rules_count,
325 &canprio_nl_rules[i], sizeof(struct can_filter));
326 rules_tmp->sff_rules_count ++;
329 canprio_sff_match_add(rules_tmp, canprio_nl_rules[i].can_id,
330 canprio_nl_rules[i].can_mask);
333 pr_debug(" can ID to match = 0x%x with mask 0x%x\n",
334 canprio_nl_rules[i].can_id, canprio_nl_rules[i].can_mask);
340 if (tb[TCA_CANPRIO_INV_EN] != NULL)
341 rules_tmp->inv_match_en = nla_get_u32(tb[TCA_CANPRIO_INV_EN]);
343 if (f->rules == NULL) { // Setting parameters for newly created filter
344 rcu_assign_pointer(f->rules, rules_tmp);
345 } else { // Changing existing filter
346 struct canprio_rules *rules_old;
348 rules_old = xchg(&f->rules, rules_tmp);
349 call_rcu(&rules_old->rcu, canprio_rules_free_rcu);
360 * Called for changing properties of an existing filter or after addition
361 * of a new filter to a class (by calling bind_tcf which binds an instance
362 * of a filter to the class).
364 * @tp: Structure representing instance of a filter.
365 * Part of a linked list of all filters.
368 * @tca: Messages passed through the Netlink from userspace.
371 static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
372 struct nlattr **tca, unsigned long *arg)
374 struct canprio_head *head = (struct canprio_head *)tp->root;
375 struct canprio_filter *f = (struct canprio_filter *)*arg;
376 struct nlattr *tb[TCA_CANPRIO_MAX + 1];
379 pr_debug("%s() invoked\n", __FUNCTION__);
381 if (tca[TCA_OPTIONS] == NULL)
384 /* Parses a stream of attributes and stores a pointer to each attribute in
385 the tb array accessible via the attribute type. Policy may be set to NULL
386 if no validation is required.*/
387 err = nla_parse_nested(tb, TCA_CANPRIO_MAX, tca[TCA_OPTIONS], canprio_policy);
390 /* Change existing filter (remove all settings and add
391 them thereafter as if filter was newly created) */
393 if (handle && f->handle != handle)
396 pr_debug("[change existing filter]\n");
397 return canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
400 /* Create new filter */
402 f = kzalloc(sizeof(*f), GFP_KERNEL);
406 if (tb[TCA_CANPRIO_CLASSID]) {
407 f->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
408 tcf_bind_filter(tp, &f->res, base);
412 if (handle) /* handle passed from userspace */
415 f->handle = canprio_gen_handle(tp);
419 err = canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
423 //Add newly created filter to list of all filters
425 list_add(&f->link, &head->flist);
427 *arg = (unsigned long) f;
432 if (*arg == 0UL && f)
439 static void canprio_delete_filter(struct tcf_proto *tp, struct canprio_filter *f)
441 tcf_unbind_filter(tp, &f->res);
444 kfree(f->rules->rules_raw);
450 * Remove whole filter.
452 static void canprio_destroy(struct tcf_proto *tp)
454 struct canprio_head *head = tp->root;
455 struct canprio_filter *f, *n;
457 list_for_each_entry_safe(f, n, &head->flist, link) {
459 canprio_delete_filter(tp, f);
465 * Delete one instance of a filter.
467 static int canprio_delete(struct tcf_proto *tp, unsigned long arg)
469 struct canprio_head *head = (struct canprio_head *)tp->root;
470 struct canprio_filter *t;
471 struct canprio_filter *f = (struct canprio_filter *)arg;
473 rcu_barrier(); /* Wait for completion of call_rcu()'s */
475 list_for_each_entry(t, &head->flist, link)
480 canprio_delete_filter(tp, t);
491 static int canprio_init(struct tcf_proto *tp)
493 struct canprio_head *head;
494 pr_debug(" canprio_init invoked\n");
496 head = kzalloc(sizeof(*head), GFP_KERNEL);
500 INIT_LIST_HEAD(&head->flist);
502 tp->protocol = htons(ETH_P_CAN); /* Work only on AF_CAN packets - not tested! */
508 * Iterates over all elements of a filter and invokes a callback function
509 * for each of them. This is used to obtain diagnostic data
511 static void canprio_walk(struct tcf_proto *tp, struct tcf_walker *arg)
513 struct canprio_head *head = (struct canprio_head *) tp->root;
514 struct canprio_filter *f;
516 pr_debug("%s() invoked\n", __FUNCTION__);
518 list_for_each_entry(f, &head->flist, link) {
519 if (arg->count < arg->skip)
522 if (arg->fn(tp, (unsigned long) f, arg) < 0) {
532 * Returns diagnostic data for a filter or one of its elements.
534 static int canprio_dump(struct tcf_proto *tp, unsigned long fh,
535 struct sk_buff *skb, struct tcmsg *t)
537 struct canprio_filter *f = (struct canprio_filter *) fh;
539 struct canprio_rules *r;
540 pr_debug("%s() invoked\n", __FUNCTION__);
546 r = rcu_dereference(f->rules);
547 t->tcm_handle = f->handle;
549 nest = nla_nest_start(skb, TCA_OPTIONS);
551 goto nla_put_failure;
554 NLA_PUT_U32(skb, TCA_CANPRIO_CLASSID, f->res.classid);
556 NLA_PUT(skb, TCA_CANPRIO_RULES, r->rules_count *
557 sizeof(struct can_filter), r->rules_raw);
560 nla_nest_end(skb, nest);
566 nla_nest_cancel(skb, nest);
572 static struct tcf_proto_ops cls_canprio_ops __read_mostly = {
574 .classify = canprio_classify,
575 .init = canprio_init,
576 .destroy = canprio_destroy,
579 .change = canprio_change,
580 .delete = canprio_delete,
581 .walk = canprio_walk,
582 .dump = canprio_dump,
583 .owner = THIS_MODULE,
586 static int __init init_canprio(void)
588 pr_debug("Canprio loaded\n");
590 pr_debug("SFF frames stored in bitmap\n");
592 pr_debug("SFF frames stored in array\n");
594 return register_tcf_proto_ops(&cls_canprio_ops);
597 static void __exit exit_canprio(void)
599 pr_debug("Canprio removed\n");
600 unregister_tcf_proto_ops(&cls_canprio_ops);
603 module_init(init_canprio);
604 module_exit(exit_canprio);
605 MODULE_LICENSE("GPL");
606 MODULE_AUTHOR(""); // FIXME
607 MODULE_DESCRIPTION("Controller Area Network can_id classifier");