From patchwork Sat Feb 9 16:45:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 219411 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 830B02C0087 for ; Sun, 10 Feb 2013 03:45:58 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932439Ab3BIQpg (ORCPT ); Sat, 9 Feb 2013 11:45:36 -0500 Received: from mail-ea0-f174.google.com ([209.85.215.174]:53628 "EHLO mail-ea0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932432Ab3BIQpe (ORCPT ); Sat, 9 Feb 2013 11:45:34 -0500 Received: by mail-ea0-f174.google.com with SMTP id 1so2114082eaa.19 for ; Sat, 09 Feb 2013 08:45:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:x-gm-message-state; bh=eGzQTXTxneT8cuumupXKeRkI/g8SMO5dSEACW9nu0OA=; b=H2o9auXWTnFP6MDVvLbf6EykrOBPY65ZZJ3SI8W6hPqjEGp6UmFKIPNVW9nbU3ChDT 5YU/kihxTOgxMwoKxbn6GF7A3LJvcehz5nwZX8FKj9IuSHKxVvUKfgi2A2SCy16slH4W AjqJe9St3BJrJEHY/kgPBcYeEJYsJ5boW8+jUqssA7wTnZlv2cvVgLHpAg5FjTt2oKk7 En7Nl0aHwJpSGli99yIZEWp/geVYzdJBIXvhduM4wEc+ffjYfq24XxeT8b2e2/p+ppL1 hy6ZgDJvAC5W7d+Jd9uv4OC/RXEoqzm1ywkaj9D4lUOpISGjzaETut0Nc/7f4lrRFjgQ Z7Mg== X-Received: by 10.14.194.195 with SMTP id m43mr29125814een.44.1360428331351; Sat, 09 Feb 2013 08:45:31 -0800 (PST) Received: from localhost (sun-0.pirko.cz. [84.16.102.25]) by mx.google.com with ESMTPS id o3sm53137628eem.15.2013.02.09.08.45.29 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 09 Feb 2013 08:45:30 -0800 (PST) From: Jiri Pirko To: netdev@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, jhs@mojatatu.com, kuznet@ms2.inr.ac.ru, j.vimal@gmail.com Subject: [patch net-next v3 05/11] sch: make htb_rate_cfg and functions around that generic Date: Sat, 9 Feb 2013 17:45:06 +0100 Message-Id: <1360428312-1277-6-git-send-email-jiri@resnulli.us> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1360428312-1277-1-git-send-email-jiri@resnulli.us> References: <1360428312-1277-1-git-send-email-jiri@resnulli.us> X-Gm-Message-State: ALoCoQmV8kQltPdH9kM/sJ5BVIkT5AK9gx2OqGmwQDq3TP+b5yU9E64FOjsl+TPAZJk+AE+zkFSk Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org As it is going to be used in tbf as well, push these to generic code. Signed-off-by: Jiri Pirko Acked-by: Eric Dumazet --- include/net/sch_generic.h | 19 ++++++++++++++ net/sched/sch_generic.c | 37 +++++++++++++++++++++++++++ net/sched/sch_htb.c | 65 +++++++---------------------------------------- 3 files changed, 65 insertions(+), 56 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 2d06c2a..2761c90 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -679,4 +679,23 @@ static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask, } #endif +struct psched_ratecfg { + u64 rate_bps; + u32 mult; + u32 shift; +}; + +static inline u64 psched_l2t_ns(const struct psched_ratecfg *r, + unsigned int len) +{ + return ((u64)len * r->mult) >> r->shift; +} + +extern void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate); + +static inline u32 psched_ratecfg_getrate(const struct psched_ratecfg *r) +{ + return r->rate_bps >> 3; +} + #endif diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 5d81a44..ffad481 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -896,3 +897,39 @@ void dev_shutdown(struct net_device *dev) WARN_ON(timer_pending(&dev->watchdog_timer)); } + +void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate) +{ + u64 factor; + u64 mult; + int shift; + + r->rate_bps = rate << 3; + r->shift = 0; + r->mult = 1; + /* + * Calibrate mult, shift so that token counting is accurate + * for smallest packet size (64 bytes). Token (time in ns) is + * computed as (bytes * 8) * NSEC_PER_SEC / rate_bps. It will + * work as long as the smallest packet transfer time can be + * accurately represented in nanosec. + */ + if (r->rate_bps > 0) { + /* + * Higher shift gives better accuracy. Find the largest + * shift such that mult fits in 32 bits. + */ + for (shift = 0; shift < 16; shift++) { + r->shift = shift; + factor = 8LLU * NSEC_PER_SEC * (1 << r->shift); + mult = div64_u64(factor, r->rate_bps); + if (mult > UINT_MAX) + break; + } + + r->shift = shift - 1; + factor = 8LLU * NSEC_PER_SEC * (1 << r->shift); + r->mult = div64_u64(factor, r->rate_bps); + } +} +EXPORT_SYMBOL(psched_ratecfg_precompute); diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 2b22544..03c2692 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -38,6 +38,7 @@ #include #include #include +#include #include /* HTB algorithm. @@ -71,12 +72,6 @@ enum htb_cmode { HTB_CAN_SEND /* class can send */ }; -struct htb_rate_cfg { - u64 rate_bps; - u32 mult; - u32 shift; -}; - /* interior & leaf nodes; props specific to leaves are marked L: */ struct htb_class { struct Qdisc_class_common common; @@ -124,8 +119,8 @@ struct htb_class { int filter_cnt; /* token bucket parameters */ - struct htb_rate_cfg rate; - struct htb_rate_cfg ceil; + struct psched_ratecfg rate; + struct psched_ratecfg ceil; s64 buffer, cbuffer; /* token bucket depth/rate */ psched_tdiff_t mbuffer; /* max wait time */ s64 tokens, ctokens; /* current number of tokens */ @@ -168,45 +163,6 @@ struct htb_sched { struct work_struct work; }; -static u64 l2t_ns(struct htb_rate_cfg *r, unsigned int len) -{ - return ((u64)len * r->mult) >> r->shift; -} - -static void htb_precompute_ratedata(struct htb_rate_cfg *r) -{ - u64 factor; - u64 mult; - int shift; - - r->shift = 0; - r->mult = 1; - /* - * Calibrate mult, shift so that token counting is accurate - * for smallest packet size (64 bytes). Token (time in ns) is - * computed as (bytes * 8) * NSEC_PER_SEC / rate_bps. It will - * work as long as the smallest packet transfer time can be - * accurately represented in nanosec. - */ - if (r->rate_bps > 0) { - /* - * Higher shift gives better accuracy. Find the largest - * shift such that mult fits in 32 bits. - */ - for (shift = 0; shift < 16; shift++) { - r->shift = shift; - factor = 8LLU * NSEC_PER_SEC * (1 << r->shift); - mult = div64_u64(factor, r->rate_bps); - if (mult > UINT_MAX) - break; - } - - r->shift = shift - 1; - factor = 8LLU * NSEC_PER_SEC * (1 << r->shift); - r->mult = div64_u64(factor, r->rate_bps); - } -} - /* find class in global hash table using given handle */ static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) { @@ -632,7 +588,7 @@ static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, s64 diff) if (toks > cl->buffer) toks = cl->buffer; - toks -= (s64) l2t_ns(&cl->rate, bytes); + toks -= (s64) psched_l2t_ns(&cl->rate, bytes); if (toks <= -cl->mbuffer) toks = 1 - cl->mbuffer; @@ -645,7 +601,7 @@ static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, s64 diff) if (toks > cl->cbuffer) toks = cl->cbuffer; - toks -= (s64) l2t_ns(&cl->ceil, bytes); + toks -= (s64) psched_l2t_ns(&cl->ceil, bytes); if (toks <= -cl->mbuffer) toks = 1 - cl->mbuffer; @@ -1134,9 +1090,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, memset(&opt, 0, sizeof(opt)); - opt.rate.rate = cl->rate.rate_bps >> 3; + opt.rate.rate = psched_ratecfg_getrate(&cl->rate); opt.buffer = PSCHED_NS2TICKS(cl->buffer); - opt.ceil.rate = cl->ceil.rate_bps >> 3; + opt.ceil.rate = psched_ratecfg_getrate(&cl->ceil); opt.cbuffer = PSCHED_NS2TICKS(cl->cbuffer); opt.quantum = cl->quantum; opt.prio = cl->prio; @@ -1503,11 +1459,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, cl->prio = TC_HTB_NUMPRIO - 1; } - cl->rate.rate_bps = (u64)hopt->rate.rate << 3; - cl->ceil.rate_bps = (u64)hopt->ceil.rate << 3; - - htb_precompute_ratedata(&cl->rate); - htb_precompute_ratedata(&cl->ceil); + psched_ratecfg_precompute(&cl->rate, hopt->rate.rate); + psched_ratecfg_precompute(&cl->ceil, hopt->ceil.rate); cl->buffer = PSCHED_TICKS2NS(hopt->buffer); cl->cbuffer = PSCHED_TICKS2NS(hopt->buffer);