]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/commitdiff
canprio_dump() is sending all rules to userspace. Some improvements in main structure...
authorRostislav Lisovy <lisovy@gmail.com>
Mon, 22 Aug 2011 13:44:33 +0000 (15:44 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Mon, 22 Aug 2011 13:44:33 +0000 (15:44 +0200)
net/sched/cls_canprio.c

index 12c471305c2c0098e28a68aa4b44387e608110a2..c344df066aa7d7bd0e66473a24d6cd19dd63a29c 100644 (file)
@@ -40,9 +40,6 @@
 #include <linux/rcupdate.h>
 #include <linux/can.h>
 
-
-struct can_filter *canprio_rules;
-int canprio_rules_count = 0;
 //--------------------------------------
 
 /* Definition of Netlink messages */
@@ -58,18 +55,30 @@ enum {
 static const struct nla_policy canprio_policy[TCA_CANPRIO_MAX + 1] = {
        [TCA_CANPRIO_CLASSID]    = { .type = NLA_U32 },
        //FIXME Be aware of possible problems with 64bit kernel and 32bit userspace etc.
-       [TCA_CANPRIO_RULES]      = { .len = (sizeof(struct can_filter)) }, //FIXME
+       [TCA_CANPRIO_RULES]      = { /*.len = (sizeof(struct can_filter))*/ }, //FIXME
        [TCA_CANPRIO_INV_EN]     = { .type = NLA_U32 },
 };
 
 struct canprio_eff_item {
        struct hlist_node list;
        struct rcu_head rcu;
-       u32 canid;
-       u32 mask;
+       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) */
+       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;
+       int sff_rules_count;
+};
+
 struct canprio_head {
        u32 hgenerator;
        struct list_head flist;
@@ -77,10 +86,7 @@ struct canprio_head {
 
 struct canprio_filter {
        u32 handle;
-       // For each SFF Can ID (11 bit) there is one record in this bitfield
-       DECLARE_BITMAP(match_sff, CAN_SFF_MASK + 1);
-       int inv_match_en; // Inverted match flag
-       struct hlist_head match_eff; // List of EFF frames to match
+       struct canprio_rules rules;
        struct tcf_result res;
        struct list_head link;
 };
@@ -98,13 +104,13 @@ static void canprio_sff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
        canid = canid & mask;
 
        if (mask == CAN_SFF_MASK) {
-               set_bit(canid, f->match_sff);
+               set_bit(canid, f->rules.match_sff);
                return;
        }
 
        for (i = 0; i <= CAN_SFF_MASK; i++) {
                if ((i & mask) == canid)
-                       set_bit(i, f->match_sff);
+                       set_bit(i, f->rules.match_sff);
        }
 }
 
@@ -123,10 +129,10 @@ static int canprio_eff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
 
        spin_lock(&canprio_match_eff_lock);
 
-       eff->canid = canid;
-       eff->mask = mask;
+       eff->rule.can_id = canid;
+       eff->rule.can_mask = mask;
 
-       hlist_add_head_rcu(&eff->list, &f->match_eff);
+       hlist_add_head_rcu(&eff->list, &f->rules.match_eff);
 
        spin_unlock(&canprio_match_eff_lock);   
        
@@ -177,8 +183,8 @@ static int canprio_classify(struct sk_buff *skb, struct tcf_proto *tp,
                        
                        rcu_read_lock();
 
-                       hlist_for_each_entry_rcu(effi, next, &f->match_eff, list) {
-                               if ((effi->canid ^ canid) & effi->mask) {
+                       hlist_for_each_entry_rcu(effi, next, &f->rules.match_eff, list) {
+                               if ((effi->rule.can_id ^ canid) & effi->rule.can_mask) {
                                        match = true;
                                        break;
                                }
@@ -186,10 +192,10 @@ static int canprio_classify(struct sk_buff *skb, struct tcf_proto *tp,
 
                        rcu_read_unlock();
                } else {
-                       match = test_bit(canid, f->match_sff);
+                       match = test_bit(canid, f->rules.match_sff);
                }
 
-               if (f->inv_match_en)
+               if (f->rules.inv_match_en)
                        match = !match;
 
                if (match) {
@@ -214,8 +220,8 @@ static int canprio_set_parms(struct tcf_proto *tp, struct canprio_filter *f,
 
        if (tb[TCA_CANPRIO_CLASSID]) {
                f->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
-               bitmap_zero(f->match_sff, CAN_SFF_MASK + 1);
-               INIT_HLIST_HEAD(&f->match_eff);
+               bitmap_zero(f->rules.match_sff, CAN_SFF_MASK + 1);
+               INIT_HLIST_HEAD(&f->rules.match_eff);
 
                tcf_bind_filter(tp, &f->res, base);
        }
@@ -300,6 +306,7 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
        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;
        
        printk(" canprio_change invoked\n");
@@ -327,7 +334,6 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
        if (f == NULL)
                goto errout;
 
-
        err = -EINVAL;
        if (handle)
                f->handle = handle;
@@ -362,29 +368,39 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
        if (tb[TCA_CANPRIO_RULES] == NULL)
                return -EINVAL;
 
-       canprio_rules = nla_data(tb[TCA_CANPRIO_RULES]);
-       canprio_rules_count = (nla_len(tb[TCA_CANPRIO_RULES]) / sizeof(struct can_filter));
-       printk(" rules_count = %u\n", canprio_rules_count);
+       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);
 
-       for (i = 0; i < canprio_rules_count; i++) {
+       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: shouldn't use here the same logic as in
                 * can_rcv_filter() to filter for various combination
                 * of flags (EFF, RTR) */
-               if (canprio_rules[i].can_id & CAN_EFF_FLAG) {
-                       err = canprio_eff_match_add(f, canprio_rules[i].can_id, canprio_rules[i].can_mask);
+               if (canprio_nl_rules[i].can_id & 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_rules[i].can_id, canprio_rules[i].can_mask);
+                       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_rules[i].can_id, canprio_rules[i].can_mask);
+                       canprio_nl_rules[i].can_id, canprio_nl_rules[i].can_mask);
        }
 
-       f->inv_match_en = 0;
+       f->rules.inv_match_en = 0;
        if (tb[TCA_CANPRIO_INV_EN] != NULL)
-               f->inv_match_en = nla_get_u32(tb[TCA_CANPRIO_INV_EN]);
+               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);
@@ -395,6 +411,9 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
        return 0;
 
 errout:
+       if (f->rules.rules_raw != NULL) //FIXME is ok?
+               kfree(f->rules.rules_raw);
+
        if (*arg == 0UL && f)
                kfree(f);
 
@@ -410,10 +429,11 @@ static void canprio_delete_filter(struct tcf_proto *tp, struct canprio_filter *f
        rcu_barrier();  
 
        tcf_unbind_filter(tp, &f->res);
-       hlist_for_each_entry_safe(effi, p, n, &f->match_eff, list) {
+       hlist_for_each_entry_safe(effi, p, n, &(f->rules.match_eff), list) {
                kfree(effi);
        }
 
+       kfree(f->rules.rules_raw);
         kfree(f);
 }
 
@@ -525,11 +545,10 @@ static int canprio_dump(struct tcf_proto *tp, unsigned long fh,
                NLA_PUT_U32(skb, TCA_CANPRIO_CLASSID, f->res.classid);
 
        
-       //NLA_PUT(skb, TCA_CANPRIO_RULES, canprio_rules_count * sizeof(struct canprio_rule), 
-       //      canprio_rules);
+       NLA_PUT(skb, TCA_CANPRIO_RULES, f->rules.rules_count * 
+               sizeof(struct can_filter), f->rules.rules_raw);
+       printk(" sending %d rules.", f->rules.rules_count);
 
-       /* ... 
-               ... */
 
        nla_nest_end(skb, nest);