]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/commitdiff
RCU list for storing EFF matches removed -- replaced with simple array.
authorRostislav Lisovy <lisovy@gmail.com>
Fri, 26 Aug 2011 21:41:20 +0000 (23:41 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Fri, 26 Aug 2011 21:41:20 +0000 (23:41 +0200)
net/sched/cls_canprio.c

index 8eba52bdd81b41a32a323f892fd3b3ec6a1aca50..60205413678e55c573cfe17e557b801b3b359d6b 100644 (file)
@@ -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)