};
struct canprio_rule *canprio_rules;
+int canprio_rules_count = 0;
//--------------------------------------
/* Definition of Netlink messages */
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(canprio_rules) }, /* FIXME */
+ [TCA_CANPRIO_RULES] = { /*.len = (sizeof(struct canprio_rule)*32)*/ }, /* FIXME */
[TCA_CANPRIO_INV_EN] = { .type = NLA_U32 },
};
u32 handle;
// For each SFF Can ID (11 bit) there is one record in this bitfield
DECLARE_BITMAP(match_sff, CAN_SFF_MASK + 1);
- int inv_match_en;
- struct hlist_head match_eff;
+ int inv_match_en; // Inverted match flag
+ struct hlist_head match_eff; // List of EFF frames to match
struct tcf_result res;
struct list_head link;
};
{
int i;
+ printk("%s() invoked\n", __FUNCTION__);
mask &= CAN_SFF_MASK;
canid = canid & mask;
struct canprio_eff_item *eff;
int err = 0;
+ printk("%s() invoked\n", __FUNCTION__);
mask &= CAN_EFF_MASK;
canid = canid & mask;
}
/*
- * Looks up a filter element by its handle and returns the internal filter ID
+ * Looks up a filter element by its handle and returns the internal
+ * filter ID (i.e. pointer)
*/
static unsigned long canprio_get(struct tcf_proto *tp, u32 handle)
{
- unsigned long l = 0UL;
- struct canprio_head *head = (struct canprio_head *) tp->root;
+ struct canprio_head *head = (struct canprio_head *)tp->root;
struct canprio_filter *f;
+ //printk("canprio_get(%d) invoked\n", handle);
if (head == NULL)
return 0UL;
- list_for_each_entry(f, &head->flist, link)
- if (f->handle == handle)
- l = (unsigned long) f;
+ //printk("[running for_each_entry]\n");
+ list_for_each_entry(f, &head->flist, link) {
+ //printk("[f->handle = %d]\n", f->handle);
+ if (f->handle == handle) {
+ //printk("found something\n");
+ return (unsigned long) f;
+ }
+ }
- return l;
+ return 0UL;
}
/*
}
+/* FIXME all functions with prefixes? */
+static unsigned int gen_handle(struct tcf_proto *tp)
+{
+ struct canprio_head *head = (struct canprio_head *)tp->root;
+ int i = 0xFFFF;
+
+ while (i-- > 0) {
+ u32 h;
+ unsigned long tmp;
+
+ if ((head->hgenerator += 0x10000) == 0)
+ head->hgenerator = 0x10000;
+
+ h = head->hgenerator;
+ //if (canprio_get(tp, h) == 0)
+ // return h;
+ tmp = canprio_get(tp, h);
+ //printk("___tried %d result %lu\n", h, tmp);
+ if (tmp == 0)
+ return h;
+ }
+ return 0;
+}
+
+
/*
* Called for changing properties of an existing filter or after addition
* of a new filter to a class (by calling bind_tcf which binds an instance
* @tp: Structure representing instance of a filter.
* Part of a linked list of all filters.
* @base:
- * @handle:
+ * @handle:
* @tca: Messages passed through the Netlink from userspace.
* @arg: ??? FIXME
*/
struct canprio_head *head = (struct canprio_head *)tp->root;
struct canprio_filter *f = (struct canprio_filter *)*arg;
struct nlattr *tb[TCA_CANPRIO_MAX + 1];
- int canprio_rules_count = 0;
int i;
printk(" canprio_change invoked\n");
if (handle)
f->handle = handle;
else {
- //FIXME wat?
+ u32 handle;
+ /*
unsigned int i = 0x80000000;
do {
if (++head->hgenerator == 0x7FFFFFFF)
pr_err("Insufficient number of handles\n");
goto errout;
}
-
- f->handle = head->hgenerator;
+ */
+ handle = gen_handle(tp);
+ //printk("__new handle %d\n", handle);
+ f->handle = handle;
+ //FIXME where is hgenerator initialized
}
static int canprio_init(struct tcf_proto *tp)
{
struct canprio_head *head;
+ //printk("tp = %p\n", tp);
+ printk(" canprio_init invoked\n");
+
+ 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;
+}
- printk(" canprio_init invoked\n");
- 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! */
+static void canprio_walk(struct tcf_proto *tp, struct tcf_walker *arg)
+{
+ struct canprio_head *head = (struct canprio_head *) tp->root;
+ struct canprio_filter *f;
+
+ printk("%s() invoked\n", __FUNCTION__);
- return 0;
+ list_for_each_entry(f, &head->flist, link) {
+ if (arg->count < arg->skip)
+ goto skip;
+
+ printk("calling canprio_dump()\n");
+ if (arg->fn(tp, (unsigned long) f, arg) < 0) {
+ arg->stop = 1;
+ break;
+ }
+skip:
+ arg->count++;
+ }
+}
+
+static int canprio_dump(struct tcf_proto *tp, unsigned long fh,
+ struct sk_buff *skb, struct tcmsg *t)
+{
+ struct canprio_filter *f = (struct canprio_filter *) fh;
+ struct nlattr *nest;
+
+ printk("%s() invoked\n", __FUNCTION__);
+
+ if (f == NULL)
+ return skb->len;
+
+ t->tcm_handle = f->handle;
+
+ nest = nla_nest_start(skb, TCA_OPTIONS);
+ if (nest == NULL)
+ goto nla_put_failure;
+
+ if (f->res.classid)
+ NLA_PUT_U32(skb, TCA_CANPRIO_CLASSID, f->res.classid);
+
+
+ //NLA_PUT(skb, TCA_CANPRIO_RULES, canprio_rules_count * sizeof(struct canprio_rule),
+ // canprio_rules);
+
+ /* ...
+ ... */
+
+ nla_nest_end(skb, nest);
+
+ return skb->len;
+
+nla_put_failure:
+ nla_nest_cancel(skb, nest);
+ return -1;
}
.put = canprio_put,
.change = canprio_change,
.delete = canprio_delete,
+ .walk = canprio_walk,
+ .dump = canprio_dump,
.owner = THIS_MODULE,
};
module_init(init_canprio);
module_exit(exit_canprio);
MODULE_LICENSE("GPL");
+MODULE_AUTHOR(""); // FIXME
+MODULE_DESCRIPTION("");