X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lisovros/linux_canprio.git/blobdiff_plain/e383184840fc8e34eb9fd38544146849e4ccdd18..28a4d0cc1e39ad67fb5dd17375c1cf90944fd255:/net/sched/cls_can.c diff --git a/net/sched/cls_can.c b/net/sched/cls_can.c index 2c2b58972b1..cf34eb56b8d 100644 --- a/net/sched/cls_can.c +++ b/net/sched/cls_can.c @@ -12,7 +12,7 @@ * (c) 2011 Volkswagen Group Research * Authors: Michal Sojka * Pavel Pisa - * Rostislav Lisovy + * Rostislav Lisovy * Funded by: Volkswagen Group Research * * Some function descriptions are heavily inspired by article "Linux Network @@ -35,11 +35,6 @@ #include #include -#ifndef CAN_SFF_ID_BITS - #define CAN_SFF_ID_BITS 11 - #define CAN_EFF_ID_BITS 29 -#endif - #define SFF_BITMAP 1 /* Use bitmap for storing rules for SFF frames? */ @@ -54,10 +49,10 @@ enum { #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 { @@ -70,7 +65,6 @@ struct canfltr_rules { ID (11 bit) there is one record in this bitfield */ #endif - int inv_match_en; /* Inverted match flag */ int rules_count; int eff_rules_count; int sff_rules_count; @@ -129,8 +123,8 @@ static void canfltr_sff_match_add(struct canfltr_rules *rls, #endif } -/* - * Extracts Can ID out of the sk_buff structure. +/** + * canfltr_get_id() - Extracts Can ID out of the sk_buff structure. */ static canid_t canfltr_get_id(struct sk_buff *skb) { @@ -140,19 +134,20 @@ static canid_t canfltr_get_id(struct sk_buff *skb) return cf->can_id; } -/* - * Performs the classification. Iterates over all instances of filter, - * checking for CAN ID match. +/** + * canfltr_classify() - Performs the classification. * * @skb: Socket buffer * @tp: * @res: Is used for setting Class ID as a result of classification * + * Iterates over all instances of filter, checking for CAN ID match. + * * Returns value relevant for policing. Used return values: * TC_POLICE_OK if succesfully classified (without regard to policing rules) * TC_POLICE_UNSPEC if no matching rule was found */ -static int canfltr_classify(struct sk_buff *skb, struct tcf_proto *tp, +static int canfltr_classify(struct sk_buff *skb, const struct tcf_proto *tp, struct tcf_result *res) { struct canfltr_head *head = (struct canfltr_head *)tp->root; @@ -173,9 +168,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; } @@ -185,9 +179,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; } @@ -206,9 +201,9 @@ static int canfltr_classify(struct sk_buff *skb, struct tcf_proto *tp, return TC_POLICE_UNSPEC; } -/* - * Looks up a filter element by its handle and returns the internal - * filter ID (i.e. pointer) +/** + * canfltr_get() - Looks up a filter element by its handle and returns the + * internal filter ID (i.e. pointer) */ static unsigned long canfltr_get(struct tcf_proto *tp, u32 handle) { @@ -226,8 +221,8 @@ static unsigned long canfltr_get(struct tcf_proto *tp, u32 handle) return 0UL; } -/* - * Is invoked when a filter element previously referenced +/** + * canfltr_put() - Is invoked when a filter element previously referenced * with get() is no longer used */ static void canfltr_put(struct tcf_proto *tp, unsigned long f) @@ -268,8 +263,8 @@ static int canfltr_set_parms(struct tcf_proto *tp, struct canfltr_state *f, int i; rules_tmp = kzalloc(sizeof(*rules_tmp), GFP_KERNEL); - if (rules_tmp == NULL) - return -ENOBUFS; /* XXX: Why not -ENOMEM? */ + if (!rules_tmp) + return -ENOBUFS; err = -EINVAL; if (tb[TCA_CANFLTR_CLASSID] == NULL) @@ -342,10 +337,10 @@ errout: return err; } -/* - * Called for changing properties of an existing filter or after addition - * of a new filter to a class (by calling bind_tcf which binds an instance - * of a filter to the class). +/** + * canfltr_change() - Called for changing properties of an existing filter or + * after addition of a new filter to a class (by calling bind_tcf which binds + * an instance of a filter to the class). * * @tp: Structure representing instance of a filter. * Part of a linked list of all filters. @@ -431,8 +426,8 @@ static void canfltr_delete_filter(struct tcf_proto *tp, kfree(f); } -/* - * Remove whole filter. +/** + * canfltr_destroy() - Remove whole filter. */ static void canfltr_destroy(struct tcf_proto *tp) { @@ -446,8 +441,8 @@ static void canfltr_destroy(struct tcf_proto *tp) kfree(head); } -/* - * Delete one instance of a filter. +/** + * canfltr_delete() - Delete one instance of a filter. */ static int canfltr_delete(struct tcf_proto *tp, unsigned long arg) { @@ -470,27 +465,33 @@ static int canfltr_delete(struct tcf_proto *tp, unsigned long arg) } -/* - * Initialize filter +/** + * canfltr_init() - Initialize filter */ static int canfltr_init(struct tcf_proto *tp) { struct canfltr_head *head; + if ((tp->protocol != htons(ETH_P_ALL)) && (tp->protocol != htons(ETH_P_CAN))) + return -1; + + /* Work only on CAN frames */ + if (tp->protocol == htons(ETH_P_ALL)) + tp->protocol = htons(ETH_P_CAN); + 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; } -/* - * Iterates over all elements of a filter and invokes a callback function - * for each of them. This is used to obtain diagnostic data +/** + * canfltr_walk() - Iterates over all elements of a filter and invokes a + * callback function for each of them. This is used to obtain diagnostic data. */ static void canfltr_walk(struct tcf_proto *tp, struct tcf_walker *arg) { @@ -510,8 +511,8 @@ skip: } } -/* - * Returns diagnostic data for a filter or one of its elements. +/** + * canfltr_dump() - Returns diagnostic data for a filter or one of its elements. */ static int canfltr_dump(struct tcf_proto *tp, unsigned long fh, struct sk_buff *skb, struct tcmsg *t) @@ -584,5 +585,5 @@ static void __exit exit_canfltr(void) module_init(init_canfltr); module_exit(exit_canfltr); MODULE_LICENSE("GPL"); -MODULE_AUTHOR(""); /* FIXME */ +MODULE_AUTHOR("Rostislav Lisovy "); MODULE_DESCRIPTION("Controller Area Network classifier");