[TCA_CANPRIO_INV_EN] = { .type = NLA_U32 },
};
-struct canprio_eff_item {
- struct hlist_node list;
- struct rcu_head rcu;
- struct can_filter rule;
-};
-static DEFINE_SPINLOCK(canprio_match_eff_lock);
-
struct canprio_rules {
struct can_filter *rules_raw; /* Raw rules copied from netlink message;
Used for sending information to userspace
- (when 'tc filter show' is invoked) */
+ (when 'tc filter show' is invoked) AND
+ when matching EFF frames*/
DECLARE_BITMAP(match_sff, CAN_SFF_MASK + 1); /* For each SFF Can ID (11 bit)
there is one record in this bitfield */
- struct hlist_head match_eff; /* List of EFF frames to match */
int inv_match_en; /* Inverted match flag */
int rules_count;
int eff_rules_count;
}
}
-static int canprio_eff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
-{
- struct canprio_eff_item *eff;
- int err = 0;
-
- printk("%s() invoked\n", __FUNCTION__);
- mask &= CAN_EFF_MASK;
- canid &= mask;
-
-
- eff = kmalloc(sizeof(struct canprio_eff_item), GFP_KERNEL);
- if (!eff)
- return -ENOMEM;
-
- spin_lock(&canprio_match_eff_lock);
-
- eff->rule.can_id = canid;
- eff->rule.can_mask = mask;
-
- hlist_add_head_rcu(&eff->list, &f->rules.match_eff);
-
- spin_unlock(&canprio_match_eff_lock);
-
- return err;
-}
-
/*
* Extracts Can ID ot ouf the sk_buff structure.
*/
struct canprio_head *head = (struct canprio_head *)tp->root;
struct canprio_filter *f;
u32 canid;
+ int i;
printk(" canprio_classify() invoked\n");
canid = (u32)canprio_get_id(skb);
bool match = false;
if (canid & CAN_EFF_FLAG) {
- struct canprio_eff_item *effi;
- struct hlist_node *next;
canid &= CAN_EFF_MASK;
- rcu_read_lock();
+ 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)) {
- 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 & effi->rule.can_mask) ==
- (canid & effi->rule.can_mask)) {
match = true;
break;
}
}
-
- rcu_read_unlock();
} else {
match = test_bit(canid, f->rules.match_sff);
}
*/
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
+ f->rules.eff_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,
int i;
printk("%s() invoked\n", __FUNCTION__);
- //if (tb[TCA_CANPRIO_CLASSID] == NULL) //FIXME is enough?
- // return -EINVAL;
+ 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);
if (f->rules.rules_raw == NULL)
return -ENOMEM;
- memcpy(f->rules.rules_raw, canprio_nl_rules,
- sizeof(struct can_filter) * f->rules.rules_count);
-
+ /* Process EFF frames */
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;
+ memcpy(f->rules.rules_raw + f->rules.eff_rules_count,
+ &canprio_nl_rules[i], sizeof(struct can_filter));
+ f->rules.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);
} else {
+ continue;
+ }
+ }
+
+ /* 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++) {
+ 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,
+ &canprio_nl_rules[i], sizeof(struct can_filter));
+ f->rules.sff_rules_count ++;
+
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);
+ 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]);
/* 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;
canprio_reset(f);
return canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
}
- printk("\n");
/* Create new filter */
err = -ENOBUFS;
bitmap_zero(f->rules.match_sff, CAN_SFF_MASK + 1);
- INIT_HLIST_HEAD(&f->rules.match_eff);
f->rules.inv_match_en = 0;
static void canprio_delete_filter(struct tcf_proto *tp, struct canprio_filter *f)
{
- struct canprio_eff_item *effi;
- struct hlist_node *p, *n;
-
- rcu_barrier();
-
tcf_unbind_filter(tp, &f->res);
- hlist_for_each_entry_safe(effi, p, n, &f->rules.match_eff, list) {
- kfree(effi);
- }
-
kfree(f->rules.rules_raw);
kfree(f);
}
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! */
+
+ return 0;
}
/*
{
struct canprio_filter *f = (struct canprio_filter *) fh;
struct nlattr *nest;
- int i;
printk("%s() invoked\n", __FUNCTION__);
if (f == NULL)