]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/commitdiff
Command 'tc filter change ...' seems to work correctly.
authorRostislav Lisovy <lisovy@gmail.com>
Wed, 24 Aug 2011 12:48:16 +0000 (14:48 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Thu, 25 Aug 2011 10:34:14 +0000 (12:34 +0200)
net/sched/cls_canprio.c

index 45b7ee9424acbfccac9cbf39edbeea0f5330cd4f..8eba52bdd81b41a32a323f892fd3b3ec6a1aca50 100644 (file)
@@ -45,7 +45,8 @@
 enum {
        TCA_CANPRIO_A_UNSPEC,
        TCA_CANPRIO_CLASSID,
-       TCA_CANPRIO_RULES,
+       TCA_CANPRIO_RULES,  /* Array of can_filter structs; We are able 
+                               to determine the length after receiving */
        TCA_CANPRIO_INV_EN, /* enable inverse rules */
        __TCA_CANPRIO_MAX,
 };
@@ -85,8 +86,9 @@ struct canprio_head {
 
 struct canprio_filter {
        u32 handle;
-       struct canprio_rules rules;
-       struct tcf_result res;
+       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;
 };
 
@@ -106,7 +108,7 @@ static void canprio_sff_match_add(struct canprio_filter *f, u32 canid, u32 mask)
                set_bit(canid, f->rules.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);
@@ -183,7 +185,7 @@ static int canprio_classify(struct sk_buff *skb, struct tcf_proto *tp,
                        rcu_read_lock();
 
                        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) ^ canid) & effi->rule.can_mask)) {
                                if ((effi->rule.can_id & effi->rule.can_mask) == 
                                        (canid & effi->rule.can_mask)) {
                                        match = true;
@@ -209,27 +211,6 @@ static int canprio_classify(struct sk_buff *skb, struct tcf_proto *tp,
        return TC_POLICE_UNSPEC;
 }
 
-/*
- * Configure filter
- */
-static int canprio_set_parms(struct tcf_proto *tp, struct canprio_filter *f,
-                          unsigned long base, struct nlattr **tb,
-                          struct nlattr *est)
-{ 
-       //int err;
-       printk(" canprio_set_parms invoked\n");
-
-       if (tb[TCA_CANPRIO_CLASSID]) {
-               f->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
-               bitmap_zero(f->rules.match_sff, CAN_SFF_MASK + 1);
-               INIT_HLIST_HEAD(&f->rules.match_eff);
-
-               tcf_bind_filter(tp, &f->res, base);
-       }
-
-       return 0;
-} 
-
 /*
  * Looks up a filter element by its handle and returns the internal 
  * filter ID (i.e. pointer)
@@ -287,6 +268,81 @@ 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)
+{
+       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
+
+       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,
+                               unsigned long base, struct nlattr **tb,
+                               struct nlattr *est)
+{
+       struct can_filter *canprio_nl_rules;
+       int err;
+       int i;
+       printk("%s() invoked\n", __FUNCTION__);
+
+       //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.rules_count = (nla_len(tb[TCA_CANPRIO_RULES]) / sizeof(struct can_filter));
+               printk(" rules_count = %u\n", f->rules.rules_count);
+
+               f->rules.rules_raw = kzalloc(sizeof(struct can_filter) * f->rules.rules_count, GFP_KERNEL);
+               if (f->rules.rules_raw == NULL)
+                       return -ENOMEM;
+
+               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++) {
+                       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;
+                       } else {
+                               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);
+               }
+       }
+
+       if (tb[TCA_CANPRIO_INV_EN] != NULL)
+               f->rules.inv_match_en = nla_get_u32(tb[TCA_CANPRIO_INV_EN]);
+
+       return 0;
+
+errout:
+       if (f->rules.rules_raw != NULL) //FIXME is ok?
+               kfree(f->rules.rules_raw);
+
+       return err;
+}
 
 /* 
  * Called for changing properties of an existing filter or after addition 
@@ -303,106 +359,67 @@ static unsigned int canprio_gen_handle(struct tcf_proto *tp)
 static int canprio_change(struct tcf_proto *tp, unsigned long base, u32 handle,
                          struct nlattr **tca, unsigned long *arg)
 {
-       int err;
        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;
+       int err;
        
-       printk(" canprio_change invoked\n");
+       printk("%s() invoked\n", __FUNCTION__);
 
        if (tca[TCA_OPTIONS] == NULL)
                return -EINVAL;
 
-       /*Parses a stream of attributes and stores a pointer to each attribute in
-         the tb array accessible via the attribute type. Policy may be set to NULL 
-         if no validation is required.*/
+       /* Parses a stream of attributes and stores a pointer to each attribute in
+       the tb array accessible via the attribute type. Policy may be set to NULL 
+       if no validation is required.*/
        err = nla_parse_nested(tb, TCA_CANPRIO_MAX, tca[TCA_OPTIONS], canprio_policy);
        if (err < 0)                
                return err;
-
-       //Change existing filter
+       /* 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;
+
+               printk("[change existing filter]\n");
+               canprio_reset(f);
                return canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
        }
+       printk("\n");
 
-       //Create new filter
+       /* Create new filter */
        err = -ENOBUFS;
        f = kzalloc(sizeof(*f), GFP_KERNEL);
        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);
+       INIT_HLIST_HEAD(&f->rules.match_eff);
+       f->rules.inv_match_en = 0;
+
+
        err = -EINVAL;
-       if (handle)
+       if (handle) /* handle passed from userspace */
                f->handle = handle;
        else {
-               u32 handle;
-       /*
-               unsigned int i = 0x80000000;
-               do {
-                       if (++head->hgenerator == 0x7FFFFFFF)
-                               head->hgenerator = 1;
-               } while (--i > 0 && canprio_get(tp, head->hgenerator));
-
-               if (i <= 0) {
-                       pr_err("Insufficient number of handles\n");
-                       goto errout;
-               }
-       */
-               handle = canprio_gen_handle(tp);        
-               //printk("__new handle %d\n", handle);
-               f->handle = handle;
-               //FIXME where is hgenerator initialized
+               //u32 handle;
+               //handle = canprio_gen_handle(tp);      
+               //f->handle = handle;
+               f->handle = 1;
        }
 
-
-       //Configure newly created filter
+       //Configure filter
        err = canprio_set_parms(tp, f, base, tb, tca[TCA_RATE]);
        if (err < 0)
                goto errout;    
 
-
-       //Parse arguments
-       if (tb[TCA_CANPRIO_RULES] == NULL)
-               return -EINVAL;
-
-       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);
-
-       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: is ok? */
-               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;
-               } else {
-                       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);
-       }
-
-       f->rules.inv_match_en = 0;
-       if (tb[TCA_CANPRIO_INV_EN] != NULL)
-               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);
        list_add(&f->link, &head->flist);
@@ -412,9 +429,6 @@ 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);
 
@@ -529,7 +543,7 @@ 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)