From b5be81f5e4ffb3d21e1c5782642f500cd0ef508e Mon Sep 17 00:00:00 2001 From: Rostislav Lisovy Date: Wed, 23 May 2012 16:22:45 +0200 Subject: [PATCH] cls_can: Handle generator now uses full 32 bits for its values. --- net/sched/cls_can.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/net/sched/cls_can.c b/net/sched/cls_can.c index 0f64fb00227..111668e41e8 100644 --- a/net/sched/cls_can.c +++ b/net/sched/cls_can.c @@ -211,23 +211,25 @@ static void canfltr_put(struct tcf_proto *tp, unsigned long f) { } +/** + * canfltr_gen_handle() - Generate handle for newly created filter + * + * This code is heavily inspired by handle generator in cls_basic.c + */ static unsigned int canfltr_gen_handle(struct tcf_proto *tp) { struct canfltr_head *head = (struct canfltr_head *)tp->root; - int i = 0xFFFF; + unsigned int i = 0x80000000; - while (i-- > 0) { - u32 h; + do { + if (++head->hgenerator == 0x7FFFFFFF) + head->hgenerator = 1; + } while (--i > 0 && canfltr_get(tp, head->hgenerator)); - head->hgenerator += 0x10000; - if (head->hgenerator == 0) - head->hgenerator = 0x10000; + if (i == 0) + return 0; - h = head->hgenerator; - if (canfltr_get(tp, h) == 0) - return h; - } - return 0; + return head->hgenerator; } static void canfltr_rules_free_rcu(struct rcu_head *rcu) @@ -374,6 +376,8 @@ static int canfltr_change(struct tcf_proto *tp, unsigned long base, u32 handle, f->handle = handle; else { f->handle = canfltr_gen_handle(tp); + if (f->handle == 0) + goto errout; } /* Configure filter */ @@ -454,7 +458,8 @@ 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))) + if ((tp->protocol != htons(ETH_P_ALL)) && + (tp->protocol != htons(ETH_P_CAN))) return -1; /* Work only on CAN frames */ -- 2.39.2