/*
* cls_canprio.c -- Canprio classifier.
- * Makes decisions accoring to Can IDs.
+ * Makes decisions accoring to controller area network (CAN) identifiers.
*
* This program is free software; you can distribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2 of
* the License.
*
+ * Idea: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
* Copyright: (c) 2011 Czech Technical University in Prague
+ * (c) 2011 Volkswagen Group Research
* Authors: Michal Sojka <sojkam1@fel.cvut.cz>
* Pavel Pisa <pisa@cmp.felk.cvut.cz>
* Rostislav Lisovy <lisovy@kormus.cz>
+ * Founded by: Volkswagen Group Research
*
+ * Some function descriptions are heavily inspired by article "Linux Network
+ * Traffic Control -- Implementation Overview" by Werner Almesberger
+ *
*
* Implementation notes;
* parameter of functions named "base" is pointer to some parent element
static const struct nla_policy canprio_policy[TCA_CANPRIO_MAX + 1] = {
[TCA_CANPRIO_CLASSID] = { .type = NLA_U32 },
//FIXME Be aware of possible problems with 64bit kernel and 32bit userspace etc.
- [TCA_CANPRIO_RULES] = { /*.len = (sizeof(struct canprio_rule)*32)*/ }, /* FIXME */
+ [TCA_CANPRIO_RULES] = { .len = (sizeof(struct canprio_rule)) }, //FIXME
[TCA_CANPRIO_INV_EN] = { .type = NLA_U32 },
};
* ----------------------------------------------------------------------------
*/
-static void sff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
+static void canprio_sff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
{
int i;
}
}
-static int eff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
+static int canprio_eff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
{
struct canprio_eff_item *eff;
int err = 0;
}
-/* FIXME all functions with prefixes? */
-static unsigned int gen_handle(struct tcf_proto *tp)
+static unsigned int canprio_gen_handle(struct tcf_proto *tp)
{
struct canprio_head *head = (struct canprio_head *)tp->root;
int i = 0xFFFF;
if (tca[TCA_OPTIONS] == NULL)
return -EINVAL;
- //Parses a stream of attributes and stores a pointer to each attribute in
- //the tb array accessible via the attribute type. Policy may be set to NULL
- //if no validation is required.
+ /*Parses a stream of attributes and stores a pointer to each attribute in
+ the tb array accessible via the attribute type. Policy may be set to NULL
+ if no validation is required.*/
err = nla_parse_nested(tb, TCA_CANPRIO_MAX, tca[TCA_OPTIONS], canprio_policy);
if (err < 0)
return err;
- //Change existing filter (?)
+ //Change existing filter
if (f != NULL) {
if (handle && f->handle != handle)
return -EINVAL;
return canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
}
- //Create new filter (?)
+ //Create new filter
err = -ENOBUFS;
f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL)
goto errout;
- //FIXME why?
err = -EINVAL;
if (handle)
f->handle = handle;
goto errout;
}
*/
- handle = gen_handle(tp);
+ handle = canprio_gen_handle(tp);
//printk("__new handle %d\n", handle);
f->handle = handle;
//FIXME where is hgenerator initialized
* can_rcv_filter() to filter for various combination
* of flags (EFF, RTR) */
if (canprio_rules[i].canid & CAN_EFF_FLAG) {
- err = eff_match_add(f, canprio_rules[i].canid, canprio_rules[i].canid_mask);
+ err = canprio_eff_match_add(f, canprio_rules[i].canid, canprio_rules[i].canid_mask);
if (err < 0)
goto errout;
} else {
- sff_match_add(f, canprio_rules[i].canid, canprio_rules[i].canid_mask);
+ canprio_sff_match_add(f, canprio_rules[i].canid, canprio_rules[i].canid_mask);
}
printk(" can ID to match = 0x%x with mask 0x%x\n",
return 0;
errout:
- if (*arg == 0UL && f) //FIXME why 0UL?
+ if (*arg == 0UL && f)
kfree(f);
return err;
return -ENOENT;
}
-//FIXME copied from cls_basic, not sure if ok;
+
+/*
+ * Initialize filter
+ */
static int canprio_init(struct tcf_proto *tp)
{
struct canprio_head *head;
head = kzalloc(sizeof(*head), GFP_KERNEL);
if (head == NULL)
return -ENOBUFS;
+
INIT_LIST_HEAD(&head->flist);
tp->root = head;
tp->protocol = htons(ETH_P_CAN); /* Work only on AF_CAN packets - not tested! */
return 0;
}
-
+/*
+ * Iterates over all elements of a filter and invokes a callback function
+ * for each of them. This is used to obtain diagnostic data
+ */
static void canprio_walk(struct tcf_proto *tp, struct tcf_walker *arg)
{
struct canprio_head *head = (struct canprio_head *) tp->root;
}
}
+/*
+ * Returns diagnostic data for a filter or one of its elements.
+ */
static int canprio_dump(struct tcf_proto *tp, unsigned long fh,
struct sk_buff *skb, struct tcmsg *t)
{
module_exit(exit_canprio);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(""); // FIXME
-MODULE_DESCRIPTION("");
+MODULE_DESCRIPTION("Controller Area Network can_id classifier");