diff options
| author | Eric Dumazet <dada1@cosmosbay.com> | 2009-05-18 22:26:37 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-05-18 22:26:37 -0400 |
| commit | 511e11e396dc596825ce04d53d7f6d579404bc01 (patch) | |
| tree | 236f3316d5577d9a4abd9ee15d4479ac7ec113b0 | |
| parent | c4ca2374312b4de819dd700e72a68395eddb5fcb (diff) | |
pkt_sched: gen_estimator: use 64 bit intermediate counters for bps
gen_estimator can overflow bps (bytes per second) with Gb links, while
it was designed with a u32 API, with a theorical limit of 34360Mbit
(2^32 bytes)
Using 64 bit intermediate avbps/brate counters can allow us to reach
this theorical limit.
Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/core/gen_estimator.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 9cc9f95b109e..6d62d4618cfc 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
| @@ -66,9 +66,9 @@ | |||
| 66 | 66 | ||
| 67 | NOTES. | 67 | NOTES. |
| 68 | 68 | ||
| 69 | * The stored value for avbps is scaled by 2^5, so that maximal | 69 | * avbps is scaled by 2^5, avpps is scaled by 2^10. |
| 70 | rate is ~1Gbit, avpps is scaled by 2^10. | 70 | * both values are reported as 32 bit unsigned values. bps can |
| 71 | 71 | overflow for fast links : max speed being 34360Mbit/sec | |
| 72 | * Minimal interval is HZ/4=250msec (it is the greatest common divisor | 72 | * Minimal interval is HZ/4=250msec (it is the greatest common divisor |
| 73 | for HZ=100 and HZ=1024 8)), maximal interval | 73 | for HZ=100 and HZ=1024 8)), maximal interval |
| 74 | is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals | 74 | is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals |
| @@ -86,9 +86,9 @@ struct gen_estimator | |||
| 86 | spinlock_t *stats_lock; | 86 | spinlock_t *stats_lock; |
| 87 | int ewma_log; | 87 | int ewma_log; |
| 88 | u64 last_bytes; | 88 | u64 last_bytes; |
| 89 | u64 avbps; | ||
| 89 | u32 last_packets; | 90 | u32 last_packets; |
| 90 | u32 avpps; | 91 | u32 avpps; |
| 91 | u32 avbps; | ||
| 92 | struct rcu_head e_rcu; | 92 | struct rcu_head e_rcu; |
| 93 | struct rb_node node; | 93 | struct rb_node node; |
| 94 | }; | 94 | }; |
| @@ -115,6 +115,7 @@ static void est_timer(unsigned long arg) | |||
| 115 | rcu_read_lock(); | 115 | rcu_read_lock(); |
| 116 | list_for_each_entry_rcu(e, &elist[idx].list, list) { | 116 | list_for_each_entry_rcu(e, &elist[idx].list, list) { |
| 117 | u64 nbytes; | 117 | u64 nbytes; |
| 118 | u64 brate; | ||
| 118 | u32 npackets; | 119 | u32 npackets; |
| 119 | u32 rate; | 120 | u32 rate; |
| 120 | 121 | ||
| @@ -125,9 +126,9 @@ static void est_timer(unsigned long arg) | |||
| 125 | 126 | ||
| 126 | nbytes = e->bstats->bytes; | 127 | nbytes = e->bstats->bytes; |
| 127 | npackets = e->bstats->packets; | 128 | npackets = e->bstats->packets; |
| 128 | rate = (nbytes - e->last_bytes)<<(7 - idx); | 129 | brate = (nbytes - e->last_bytes)<<(7 - idx); |
| 129 | e->last_bytes = nbytes; | 130 | e->last_bytes = nbytes; |
| 130 | e->avbps += ((long)rate - (long)e->avbps) >> e->ewma_log; | 131 | e->avbps += ((s64)(brate - e->avbps)) >> e->ewma_log; |
| 131 | e->rate_est->bps = (e->avbps+0xF)>>5; | 132 | e->rate_est->bps = (e->avbps+0xF)>>5; |
| 132 | 133 | ||
| 133 | rate = (npackets - e->last_packets)<<(12 - idx); | 134 | rate = (npackets - e->last_packets)<<(12 - idx); |
