struct canprio_filter {
u32 handle;
- struct canprio_rules rules; /* All rules necessary for classification */
+ 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;
* ----------------------------------------------------------------------------
*/
-static void canprio_sff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
+static void canprio_sff_match_add(struct canprio_rules *rls, u32 canid, u32 mask)
{
int i;
canid &= mask;
if (mask == CAN_SFF_MASK) {
- set_bit(canid, f->rules.match_sff);
+ set_bit(canid, rls->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);
+ set_bit(i, rls->match_sff);
}
}
if (canid & CAN_EFF_FLAG) {
canid &= CAN_EFF_MASK;
- for (i = 0; i < f->rules.eff_rules_count; i++) {
- if ((f->rules.rules_raw[i].can_id & f->rules.rules_raw[i].can_mask & CAN_EFF_MASK) ==
- (canid & f->rules.rules_raw[i].can_mask & CAN_EFF_MASK)) {
+ for (i = 0; i < f->rules->eff_rules_count; i++) {
+ if ((f->rules->rules_raw[i].can_id & f->rules->rules_raw[i].can_mask & CAN_EFF_MASK) ==
+ (canid & f->rules->rules_raw[i].can_mask & CAN_EFF_MASK)) {
match = true;
break;
}
}
} else {
- match = test_bit(canid, f->rules.match_sff);
+ match = test_bit(canid, f->rules->match_sff);
}
- //if (f->rules.inv_match_en)
+ //if (f->rules->inv_match_en)
// match = !match;
if (match) {
return 0;
}
-/*
- * Reset filter to default (blank) settings
- */
-static void canprio_reset(struct canprio_filter *f)
-{
- 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
- f->rules.eff_rules_count = 0; //FIXME not necessary
-
-}
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;
+ struct canprio_rules *rules_tmp;
int err;
int i;
printk("%s() invoked\n", __FUNCTION__);
+ rules_tmp = kzalloc(sizeof(*rules_tmp), GFP_KERNEL);
+ if (rules_tmp == NULL)
+ return -ENOBUFS;
+
+ bitmap_zero(rules_tmp->match_sff, CAN_SFF_MASK + 1);
+ rules_tmp->inv_match_en = 0;
+
+
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.sff_rules_count = 0;
- f->rules.eff_rules_count = 0;
- f->rules.rules_count = (nla_len(tb[TCA_CANPRIO_RULES]) / sizeof(struct can_filter));
- printk(" rules_count = %u\n", f->rules.rules_count);
+ rules_tmp->sff_rules_count = 0;
+ rules_tmp->eff_rules_count = 0;
+ rules_tmp->rules_count = (nla_len(tb[TCA_CANPRIO_RULES]) / sizeof(struct can_filter));
+ printk(" rules_count = %u\n", rules_tmp->rules_count);
- f->rules.rules_raw = kzalloc(sizeof(struct can_filter) * f->rules.rules_count, GFP_KERNEL);
- if (f->rules.rules_raw == NULL)
+ rules_tmp->rules_raw = kzalloc(sizeof(struct can_filter) * rules_tmp->rules_count, GFP_KERNEL);
+ if (rules_tmp->rules_raw == NULL)
return -ENOMEM;
/* Process EFF frames */
- for (i = 0; i < f->rules.rules_count; i++) {
+ for (i = 0; i < rules_tmp->rules_count; i++) {
if ((canprio_nl_rules[i].can_id & CAN_EFF_FLAG) &&
(canprio_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
- memcpy(f->rules.rules_raw + f->rules.eff_rules_count,
+ memcpy(rules_tmp->rules_raw + rules_tmp->eff_rules_count,
&canprio_nl_rules[i], sizeof(struct can_filter));
- f->rules.eff_rules_count ++;
+ rules_tmp->eff_rules_count ++;
printk(" can ID to match = 0x%x with mask 0x%x\n",
canprio_nl_rules[i].can_id, canprio_nl_rules[i].can_mask);
/* Process SFF frames
We need two for() loops for copying rules into two contiguous areas in rules_raw */
- for (i = 0; i < f->rules.rules_count; i++) {
+ for (i = 0; i < rules_tmp->rules_count; i++) {
if ((canprio_nl_rules[i].can_id & CAN_EFF_FLAG) &&
(canprio_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
continue;
} else {
- memcpy(f->rules.rules_raw + f->rules.eff_rules_count + f->rules.sff_rules_count,
+ memcpy(rules_tmp->rules_raw + rules_tmp->eff_rules_count + rules_tmp->sff_rules_count,
&canprio_nl_rules[i], sizeof(struct can_filter));
- f->rules.sff_rules_count ++;
+ rules_tmp->sff_rules_count ++;
- canprio_sff_match_add(f, canprio_nl_rules[i].can_id,
+ canprio_sff_match_add(rules_tmp, canprio_nl_rules[i].can_id,
canprio_nl_rules[i].can_mask);
printk(" can ID to match = 0x%x with mask 0x%x\n",
if (tb[TCA_CANPRIO_INV_EN] != NULL)
- f->rules.inv_match_en = nla_get_u32(tb[TCA_CANPRIO_INV_EN]);
+ rules_tmp->inv_match_en = nla_get_u32(tb[TCA_CANPRIO_INV_EN]);
+
+ if (f->rules == NULL) { // Setting parameters for newly created filter
+ f->rules = rules_tmp;
+ } else { // Changing existing filter
+ struct canprio_rules *rules_old;
+
+ rules_old = f->rules;
+ f->rules = rules_tmp;
+ kfree(rules_old);
+ }
return 0;
errout:
- if (f->rules.rules_raw != NULL) //FIXME is ok?
- kfree(f->rules.rules_raw);
+ if (rules_tmp->rules_raw != NULL) //FIXME is ok?
+ kfree(rules_tmp->rules_raw);
return err;
}
return -EINVAL;
printk("[change existing filter]\n");
- canprio_reset(f);
return canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
}
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);
- f->rules.inv_match_en = 0;
-
-
err = -EINVAL;
if (handle) /* handle passed from userspace */
f->handle = handle;
return 0;
+
errout:
if (*arg == 0UL && f)
kfree(f);
static void canprio_delete_filter(struct tcf_proto *tp, struct canprio_filter *f)
{
tcf_unbind_filter(tp, &f->res);
- kfree(f->rules.rules_raw);
+ kfree(f->rules->rules_raw);
+ kfree(f->rules);
kfree(f);
}
if (f->res.classid)
NLA_PUT_U32(skb, TCA_CANPRIO_CLASSID, f->res.classid);
- NLA_PUT(skb, TCA_CANPRIO_RULES, f->rules.rules_count *
- sizeof(struct can_filter), f->rules.rules_raw);
+ NLA_PUT(skb, TCA_CANPRIO_RULES, f->rules->rules_count *
+ sizeof(struct can_filter), f->rules->rules_raw);
nla_nest_end(skb, nest);