enum {
TCA_CANPRIO_A_UNSPEC,
TCA_CANPRIO_CLASSID,
- TCA_CANPRIO_RULES,
+ TCA_CANPRIO_RULES, /* Array of can_filter structs; We are able
+ to determine the length after receiving */
TCA_CANPRIO_INV_EN, /* enable inverse rules */
__TCA_CANPRIO_MAX,
};
struct canprio_filter {
u32 handle;
- struct canprio_rules rules;
- struct tcf_result res;
+ struct canprio_rules rules; /* All rules necessary for classification */
+ struct tcf_result res; /* Class ID (flow id) the instance
+ of a filter is bound to */
struct list_head link;
};
set_bit(canid, f->rules.match_sff);
return;
}
-
+ /* Add record (set bit to 1) for each ID that conforms particular rule */
for (i = 0; i <= CAN_SFF_MASK; i++) {
if ((i & mask) == canid)
set_bit(i, f->rules.match_sff);
rcu_read_lock();
hlist_for_each_entry_rcu(effi, next, &f->rules.match_eff, list) {
- //if (((effi->rule.can_id) ^ canid) & effi->rule.can_mask) {
+ //if (!(((effi->rule.can_id) ^ canid) & effi->rule.can_mask)) {
if ((effi->rule.can_id & effi->rule.can_mask) ==
(canid & effi->rule.can_mask)) {
match = true;
return TC_POLICE_UNSPEC;
}
-/*
- * Configure filter
- */
-static int canprio_set_parms(struct tcf_proto *tp, struct canprio_filter *f,
- unsigned long base, struct nlattr **tb,
- struct nlattr *est)
-{
- //int err;
- printk(" canprio_set_parms invoked\n");
-
- if (tb[TCA_CANPRIO_CLASSID]) {
- f->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
- bitmap_zero(f->rules.match_sff, CAN_SFF_MASK + 1);
- INIT_HLIST_HEAD(&f->rules.match_eff);
-
- tcf_bind_filter(tp, &f->res, base);
- }
-
- return 0;
-}
-
/*
* Looks up a filter element by its handle and returns the internal
* filter ID (i.e. pointer)
return 0;
}
+/*
+ * Reset filter to default (blank) settings
+ */
+static void canprio_reset(struct canprio_filter *f)
+{
+ struct canprio_eff_item *effi;
+ struct hlist_node *p, *n;
+
+ if (f->rules.rules_raw != NULL)
+ kfree(f->rules.rules_raw);
+
+ bitmap_zero(f->rules.match_sff, CAN_SFF_MASK + 1);
+ f->rules.inv_match_en = 0;
+ f->rules.rules_count = 0; //FIXME not necessary
+
+ rcu_barrier();
+ hlist_for_each_entry_safe(effi, p, n, &f->rules.match_eff, list) {
+ kfree(effi);
+ }
+ INIT_HLIST_HEAD(&f->rules.match_eff);
+}
+
+static int canprio_set_parms(struct tcf_proto *tp, struct canprio_filter *f,
+ unsigned long base, struct nlattr **tb,
+ struct nlattr *est)
+{
+ struct can_filter *canprio_nl_rules;
+ int err;
+ int i;
+ printk("%s() invoked\n", __FUNCTION__);
+
+ //if (tb[TCA_CANPRIO_CLASSID] == NULL) //FIXME is enough?
+ // return -EINVAL;
+
+ if (tb[TCA_CANPRIO_RULES]) {
+ canprio_nl_rules = nla_data(tb[TCA_CANPRIO_RULES]);
+ f->rules.rules_count = (nla_len(tb[TCA_CANPRIO_RULES]) / sizeof(struct can_filter));
+ printk(" rules_count = %u\n", f->rules.rules_count);
+
+ f->rules.rules_raw = kzalloc(sizeof(struct can_filter) * f->rules.rules_count, GFP_KERNEL);
+ if (f->rules.rules_raw == NULL)
+ return -ENOMEM;
+
+ memcpy(f->rules.rules_raw, canprio_nl_rules,
+ sizeof(struct can_filter) * f->rules.rules_count);
+
+ for (i = 0; i < f->rules.rules_count; i++) {
+ if ((canprio_nl_rules[i].can_id & CAN_EFF_FLAG) &&
+ (canprio_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
+
+ err = canprio_eff_match_add(f, canprio_nl_rules[i].can_id,
+ canprio_nl_rules[i].can_mask);
+ if (err < 0)
+ goto errout;
+ } else {
+ canprio_sff_match_add(f, canprio_nl_rules[i].can_id,
+ canprio_nl_rules[i].can_mask);
+ }
+
+ printk(" can ID to match = 0x%x with mask 0x%x\n",
+ canprio_nl_rules[i].can_id, canprio_nl_rules[i].can_mask);
+ }
+ }
+
+ if (tb[TCA_CANPRIO_INV_EN] != NULL)
+ f->rules.inv_match_en = nla_get_u32(tb[TCA_CANPRIO_INV_EN]);
+
+ return 0;
+
+errout:
+ if (f->rules.rules_raw != NULL) //FIXME is ok?
+ kfree(f->rules.rules_raw);
+
+ return err;
+}
/*
* Called for changing properties of an existing filter or after addition
static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, unsigned long *arg)
{
- int err;
struct canprio_head *head = (struct canprio_head *)tp->root;
struct canprio_filter *f = (struct canprio_filter *)*arg;
struct nlattr *tb[TCA_CANPRIO_MAX + 1];
- struct can_filter *canprio_nl_rules;
- int i;
+ int err;
- printk(" canprio_change invoked\n");
+ printk("%s() invoked\n", __FUNCTION__);
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 (remove all settings and add
+ them thereafter as if filter was newly created) */
if (f != NULL) {
+ printk("%p\n", f);
if (handle && f->handle != handle)
return -EINVAL;
+
+ printk("[change existing filter]\n");
+ canprio_reset(f);
return canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
}
+ printk("\n");
- //Create new filter
+ /* Create new filter */
err = -ENOBUFS;
f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL)
goto errout;
+ if (tb[TCA_CANPRIO_CLASSID]) {
+ f->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
+ tcf_bind_filter(tp, &f->res, base);
+ }
+
+
+ bitmap_zero(f->rules.match_sff, CAN_SFF_MASK + 1);
+ INIT_HLIST_HEAD(&f->rules.match_eff);
+ f->rules.inv_match_en = 0;
+
+
err = -EINVAL;
- if (handle)
+ if (handle) /* handle passed from userspace */
f->handle = handle;
else {
- u32 handle;
- /*
- unsigned int i = 0x80000000;
- do {
- if (++head->hgenerator == 0x7FFFFFFF)
- head->hgenerator = 1;
- } while (--i > 0 && canprio_get(tp, head->hgenerator));
-
- if (i <= 0) {
- pr_err("Insufficient number of handles\n");
- goto errout;
- }
- */
- handle = canprio_gen_handle(tp);
- //printk("__new handle %d\n", handle);
- f->handle = handle;
- //FIXME where is hgenerator initialized
+ //u32 handle;
+ //handle = canprio_gen_handle(tp);
+ //f->handle = handle;
+ f->handle = 1;
}
-
- //Configure newly created filter
+ //Configure filter
err = canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
if (err < 0)
goto errout;
-
- //Parse arguments
- if (tb[TCA_CANPRIO_RULES] == NULL)
- return -EINVAL;
-
- canprio_nl_rules = nla_data(tb[TCA_CANPRIO_RULES]);
- f->rules.rules_count = (nla_len(tb[TCA_CANPRIO_RULES]) / sizeof(struct can_filter));
- printk(" rules_count = %u\n", f->rules.rules_count);
-
- err = -ENOMEM;//FIXME ENOBUFS?
- f->rules.rules_raw = kzalloc(sizeof(struct can_filter) * f->rules.rules_count, GFP_KERNEL);
- if (f->rules.rules_raw == NULL)
- goto errout;
-
- memcpy(f->rules.rules_raw, canprio_nl_rules,
- sizeof(struct can_filter) * f->rules.rules_count);
-
- for (i = 0; i < f->rules.rules_count; i++) {
- /* FIXME: is ok? */
- if (canprio_nl_rules[i].can_id & CAN_EFF_FLAG &&
- canprio_nl_rules[i].can_mask & CAN_EFF_FLAG) {
-
- err = canprio_eff_match_add(f, canprio_nl_rules[i].can_id,
- canprio_nl_rules[i].can_mask);
- if (err < 0)
- goto errout;
- } else {
- canprio_sff_match_add(f, canprio_nl_rules[i].can_id,
- canprio_nl_rules[i].can_mask);
- }
-
- printk(" can ID to match = 0x%x with mask 0x%x\n",
- canprio_nl_rules[i].can_id, canprio_nl_rules[i].can_mask);
- }
-
- f->rules.inv_match_en = 0;
- if (tb[TCA_CANPRIO_INV_EN] != NULL)
- f->rules.inv_match_en = nla_get_u32(tb[TCA_CANPRIO_INV_EN]);
-
//Add newly created filter to list of all filters
tcf_tree_lock(tp);
list_add(&f->link, &head->flist);
return 0;
errout:
- if (f->rules.rules_raw != NULL) //FIXME is ok?
- kfree(f->rules.rules_raw);
-
if (*arg == 0UL && f)
kfree(f);
{
struct canprio_filter *f = (struct canprio_filter *) fh;
struct nlattr *nest;
-
+ int i;
printk("%s() invoked\n", __FUNCTION__);
if (f == NULL)