Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352419
b: refs/heads/master
c: 292f1c7
h: refs/heads/master
i:
  352417: df2c79a
  352415: 68015d8
v: v3
  • Loading branch information
Jiri Pirko authored and David S. Miller committed Feb 12, 2013
1 parent 2b6adab commit 089da9a
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 57 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b9a7afdefdf90dc9e64902b2565170b8b017aa75
refs/heads/master: 292f1c7ff6cc10516076ceeea45ed11833bb71c7
19 changes: 19 additions & 0 deletions trunk/include/net/sch_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
37 changes: 37 additions & 0 deletions trunk/net/sched/sch_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <net/sch_generic.h>
#include <net/pkt_sched.h>
#include <net/dst.h>

Expand Down Expand Up @@ -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);
65 changes: 9 additions & 56 deletions trunk/net/sched/sch_htb.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <net/netlink.h>
#include <net/sch_generic.h>
#include <net/pkt_sched.h>

/* HTB algorithm.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 089da9a

Please sign in to comment.