]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/commitdiff
struct canprio_rules allocated dynamically -- this makes changing attributes of exist...
authorRostislav Lisovy <lisovy@gmail.com>
Mon, 29 Aug 2011 11:15:13 +0000 (13:15 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Mon, 29 Aug 2011 11:15:13 +0000 (13:15 +0200)
net/sched/cls_canprio.c

index 60205413678e55c573cfe17e557b801b3b359d6b..390a14958cd1570c61e4e04b903cd4f89e97c9cc 100644 (file)
@@ -79,7 +79,7 @@ struct canprio_head {
 
 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;
@@ -89,7 +89,7 @@ struct canprio_filter {
  * ----------------------------------------------------------------------------
  */
 
-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;
 
@@ -98,13 +98,13 @@ static void canprio_sff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
        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);
        }
 }
 
@@ -148,19 +148,19 @@ static int canprio_classify(struct sk_buff *skb, struct tcf_proto *tp,
                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) {
@@ -230,52 +230,47 @@ static unsigned int canprio_gen_handle(struct tcf_proto *tp)
        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);
@@ -286,17 +281,17 @@ static int canprio_set_parms(struct tcf_proto *tp, struct canprio_filter *f,
 
                /* 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",
@@ -307,13 +302,23 @@ static int canprio_set_parms(struct tcf_proto *tp, struct canprio_filter *f,
 
 
        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;
 }
@@ -356,7 +361,6 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
                        return -EINVAL;
 
                printk("[change existing filter]\n");
-               canprio_reset(f);
                return canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
        }
 
@@ -366,16 +370,13 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
        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;
@@ -399,6 +400,7 @@ static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 
        return 0;
 
+
 errout:
        if (*arg == 0UL && f)
                kfree(f);
@@ -410,7 +412,8 @@ errout:
 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);
 }
 
@@ -518,8 +521,8 @@ static int canprio_dump(struct tcf_proto *tp, unsigned long fh,
        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);