From: Rostislav Lisovy Date: Fri, 26 Aug 2011 21:41:20 +0000 (+0200) Subject: RCU list for storing EFF matches removed -- replaced with simple array. X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lisovros/linux_canprio.git/commitdiff_plain/847139cdd5be59e514e6e8da6ea3ca5242f4bdf8 RCU list for storing EFF matches removed -- replaced with simple array. --- diff --git a/net/sched/cls_canprio.c b/net/sched/cls_canprio.c index 8eba52bdd81..60205413678 100644 --- a/net/sched/cls_canprio.c +++ b/net/sched/cls_canprio.c @@ -59,20 +59,13 @@ static const struct nla_policy canprio_policy[TCA_CANPRIO_MAX + 1] = { [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; @@ -115,32 +108,6 @@ static void canprio_sff_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; - - 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. */ @@ -170,6 +137,7 @@ static int canprio_classify(struct sk_buff *skb, struct tcf_proto *tp, 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); @@ -178,22 +146,16 @@ static int canprio_classify(struct sk_buff *skb, struct tcf_proto *tp, 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); } @@ -273,21 +235,14 @@ static unsigned int canprio_gen_handle(struct tcf_proto *tp) */ 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, @@ -299,11 +254,13 @@ 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); @@ -311,27 +268,44 @@ static int canprio_set_parms(struct tcf_proto *tp, struct canprio_filter *f, 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]); @@ -378,7 +352,6 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle, /* 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; @@ -386,7 +359,6 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle, canprio_reset(f); return canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]); } - printk("\n"); /* Create new filter */ err = -ENOBUFS; @@ -401,7 +373,6 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle, bitmap_zero(f->rules.match_sff, CAN_SFF_MASK + 1); - INIT_HLIST_HEAD(&f->rules.match_eff); f->rules.inv_match_en = 0; @@ -438,16 +409,7 @@ errout: 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); } @@ -497,18 +459,17 @@ static int canprio_delete(struct tcf_proto *tp, unsigned long arg) 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; } /* @@ -543,7 +504,6 @@ static int canprio_dump(struct tcf_proto *tp, unsigned long fh, { struct canprio_filter *f = (struct canprio_filter *) fh; struct nlattr *nest; - int i; printk("%s() invoked\n", __FUNCTION__); if (f == NULL)