]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/blobdiff - net/sched/cls_can.c
cls_can: Fixed nla_policy.
[lisovros/linux_canprio.git] / net / sched / cls_can.c
index 046ce4a18bb2ee0f1195c89b1b98d5ab5150ea2c..815ee05f7bcb2b10b3025c00740ccf876f3d71be 100644 (file)
   #define CAN_EFF_ID_BITS      29
 #endif
 
-#define SFF_BITMAP             1
+#define SFF_BITMAP             1       /* Use bitmap for storing rules
+                                       for SFF frames? */
 
-/* Definition of Netlink messages */
+/* Definition of Netlink message parts */
 enum {
        TCA_CANFLTR_UNSPEC,
        TCA_CANFLTR_CLASSID,
-       TCA_CANFLTR_RULES,  /* Array of can_filter structs; We are able
+       TCA_CANFLTR_RULES,      /* Array of can_filter structs; We are able
                                to determine the length after receiving */
        __TCA_CANFLTR_MAX
 };
 #define TCA_CANFLTR_MAX (__TCA_CANFLTR_MAX - 1)
 
 static const struct nla_policy canfltr_policy[TCA_CANFLTR_MAX + 1] = {
-       [TCA_CANFLTR_CLASSID]    = { .type = NLA_U32 },
-       /* FIXME Be aware of possible problems with 64bit kernel and
-               32bit userspace etc. */
-       [TCA_CANFLTR_RULES]      = { /*.len = (sizeof(struct can_filter))*/ } /* FIXME */
+       [TCA_CANFLTR_CLASSID]    = { .type = NLA_U32 }, /* Be aware of possible
+                                               problems with 64bit kernel and
+                                               32bit userspace etc. */
+       [TCA_CANFLTR_RULES]      = { .type = NLA_NESTED }
 };
 
 struct canfltr_rules {
-       struct can_filter *rules_raw;   /* Raw rules copied from netlink message;
-                                       Used for sending information to userspace
-                                       (when 'tc filter show' is invoked) AND
-                                       when matching EFF frames*/
+       struct can_filter *rules_raw;   /* Raw rules copied from netlink
+                                       message; Used for sending information
+                                       to userspace (when 'tc filter show' is
+                                       invoked) AND when matching EFF frames*/
 #ifdef SFF_BITMAP
-       DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS)); /* For each SFF Can
+       DECLARE_BITMAP(match_sff, (1 << CAN_SFF_ID_BITS)); /* For each SFF CAN
                                        ID (11 bit) there is one record in this
                                        bitfield */
 #endif
@@ -84,7 +85,8 @@ struct canfltr_head {
 
 struct canfltr_state {
        u32 handle;
-       struct canfltr_rules *rules;    /* All rules necessary for classification */
+       struct canfltr_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;
@@ -94,7 +96,8 @@ struct canfltr_state {
  * ----------------------------------------------------------------------------
  */
 
-static void canfltr_sff_match_add(struct canfltr_rules *rls, u32 can_id, u32 can_mask)
+static void canfltr_sff_match_add(struct canfltr_rules *rls,
+                               u32 can_id, u32 can_mask)
 {
 #ifdef SFF_BITMAP
        int i;
@@ -117,7 +120,8 @@ static void canfltr_sff_match_add(struct canfltr_rules *rls, u32 can_id, u32 can
        }
 
        /* individual frame filter */
-       /* Add record (set bit to 1) for each ID that conforms particular rule */
+       /* Add record (set bit to 1) for each ID that
+       conforms particular rule */
        for (i = 0; i < (1 << CAN_SFF_ID_BITS); i++) {
                if ((i & can_mask) == can_id)
                        set_bit(i, rls->match_sff);
@@ -169,9 +173,8 @@ static int canfltr_classify(struct sk_buff *skb, struct tcf_proto *tp,
                        can_id &= CAN_EFF_MASK;
 
                        for (i = 0; i < r->eff_rules_count; i++) {
-                               /* XXX: Why aren't these & performed "off-line"? */
-                               if ((r->rules_raw[i].can_id & r->rules_raw[i].can_mask & CAN_EFF_MASK) ==
-                               (can_id & r->rules_raw[i].can_mask & CAN_EFF_MASK)) {
+                               if (!(((r->rules_raw[i].can_id ^ can_id) &
+                               r->rules_raw[i].can_mask) & CAN_EFF_MASK)) {
                                        match = true;
                                        break;
                                }
@@ -181,9 +184,10 @@ static int canfltr_classify(struct sk_buff *skb, struct tcf_proto *tp,
 #ifdef SFF_BITMAP
                        match = test_bit(can_id, r->match_sff);
 #else
-                       for (i = r->eff_rules_count; i < r->eff_rules_count + r->sff_rules_count; i++) {
-                               if ((r->rules_raw[i].can_id & r->rules_raw[i].can_mask & CAN_SFF_MASK) == /* XXX: dtto */
-                                   (can_id & r->rules_raw[i].can_mask & CAN_SFF_MASK)) {
+                       for (i = r->eff_rules_count;
+                       i < r->eff_rules_count + r->sff_rules_count; i++) {
+                               if (!(((r->rules_raw[i].can_id ^ can_id) &
+                               r->rules_raw[i].can_mask) & CAN_SFF_MASK)) {
                                        match = true;
                                        break;
                                }
@@ -275,23 +279,26 @@ static int canfltr_set_parms(struct tcf_proto *tp, struct canfltr_state *f,
                canfltr_nl_rules = nla_data(tb[TCA_CANFLTR_RULES]);
                rules_tmp->sff_rules_count = 0;
                rules_tmp->eff_rules_count = 0;
-               rules_tmp->rules_count =
-                       (nla_len(tb[TCA_CANFLTR_RULES]) / sizeof(struct can_filter));
+               rules_tmp->rules_count = (nla_len(tb[TCA_CANFLTR_RULES]) /
+                       sizeof(struct can_filter));
 
-               rules_tmp->rules_raw =
-                       kzalloc(sizeof(struct can_filter) * rules_tmp->rules_count, GFP_KERNEL);
+               rules_tmp->rules_raw = kzalloc(sizeof(struct can_filter) *
+                       rules_tmp->rules_count, GFP_KERNEL);
                err = -ENOMEM;
                if (rules_tmp->rules_raw == NULL)
                        goto errout;
 
-               /* We need two for() loops for copying rules into two contiguous areas in rules_raw */
+               /* We need two for() loops for copying rules into
+               two contiguous areas in rules_raw */
 
                /* Process EFF frame rules*/
                for (i = 0; i < rules_tmp->rules_count; i++) {
                        if ((canfltr_nl_rules[i].can_id & CAN_EFF_FLAG) &&
                            (canfltr_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
-                               memcpy(rules_tmp->rules_raw + rules_tmp->eff_rules_count,
-                                      &canfltr_nl_rules[i], sizeof(struct can_filter));
+                               memcpy(rules_tmp->rules_raw +
+                                       rules_tmp->eff_rules_count,
+                                       &canfltr_nl_rules[i],
+                                       sizeof(struct can_filter));
                                rules_tmp->eff_rules_count++;
                        } else {
                                continue;
@@ -304,18 +311,22 @@ static int canfltr_set_parms(struct tcf_proto *tp, struct canfltr_state *f,
                            (canfltr_nl_rules[i].can_mask & CAN_EFF_FLAG)) {
                                continue;
                        } else {
-                               memcpy(rules_tmp->rules_raw + rules_tmp->eff_rules_count +
+                               memcpy(rules_tmp->rules_raw +
+                                       rules_tmp->eff_rules_count +
                                        rules_tmp->sff_rules_count,
-                                       &canfltr_nl_rules[i], sizeof(struct can_filter));
+                                       &canfltr_nl_rules[i],
+                                       sizeof(struct can_filter));
                                rules_tmp->sff_rules_count++;
-                               canfltr_sff_match_add(rules_tmp, canfltr_nl_rules[i].can_id,
-                                                     canfltr_nl_rules[i].can_mask);
+                               canfltr_sff_match_add(rules_tmp,
+                                       canfltr_nl_rules[i].can_id,
+                                       canfltr_nl_rules[i].can_mask);
                        }
                }
        }
 
 
-       if (f->rules == NULL) { /* Setting parameters for newly created filter */
+       /* Setting parameters for newly created filter */
+       if (f->rules == NULL) {
                rcu_assign_pointer(f->rules, rules_tmp);
        } else { /* Changing existing filter */
                struct canfltr_rules *rules_old;
@@ -409,7 +420,8 @@ errout:
 }
 
 
-static void canfltr_delete_filter(struct tcf_proto *tp, struct canfltr_state *f)
+static void canfltr_delete_filter(struct tcf_proto *tp,
+                               struct canfltr_state *f)
 {
        tcf_unbind_filter(tp, &f->res);