2 * net/sched/gen_estimator.c Simple rate estimator.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 * Eric Dumazet <edumazet@google.com>
13 * Jamal Hadi Salim - moved it to net/core and reshulfed
14 * names to make it usable in general net subsystem.
17 #include <linux/uaccess.h>
18 #include <linux/bitops.h>
19 #include <linux/module.h>
20 #include <linux/types.h>
21 #include <linux/kernel.h>
22 #include <linux/jiffies.h>
23 #include <linux/string.h>
25 #include <linux/socket.h>
26 #include <linux/sockios.h>
28 #include <linux/errno.h>
29 #include <linux/interrupt.h>
30 #include <linux/netdevice.h>
31 #include <linux/skbuff.h>
32 #include <linux/rtnetlink.h>
33 #include <linux/init.h>
34 #include <linux/slab.h>
35 #include <linux/seqlock.h>
37 #include <net/gen_stats.h>
39 /* This code is NOT intended to be used for statistics collection,
40 * its purpose is to provide a base for statistical multiplexing
41 * for controlled load service.
42 * If you need only statistics, run a user level daemon which
43 * periodically reads byte counters.
46 struct net_rate_estimator
{
47 struct gnet_stats_basic_packed
*bstats
;
48 spinlock_t
*stats_lock
;
50 struct gnet_stats_basic_cpu __percpu
*cpu_bstats
;
52 u8 intvl_log
; /* period : (250ms << intvl_log) */
61 unsigned long next_jiffies
;
62 struct timer_list timer
;
66 static void est_fetch_counters(struct net_rate_estimator
*e
,
67 struct gnet_stats_basic_packed
*b
)
69 memset(b
, 0, sizeof(*b
));
71 spin_lock(e
->stats_lock
);
73 __gnet_stats_copy_basic(e
->running
, b
, e
->cpu_bstats
, e
->bstats
);
76 spin_unlock(e
->stats_lock
);
80 static void est_timer(struct timer_list
*t
)
82 struct net_rate_estimator
*est
= from_timer(est
, t
, timer
);
83 struct gnet_stats_basic_packed b
;
86 est_fetch_counters(est
, &b
);
87 brate
= (b
.bytes
- est
->last_bytes
) << (10 - est
->ewma_log
- est
->intvl_log
);
88 brate
-= (est
->avbps
>> est
->ewma_log
);
90 rate
= (u64
)(b
.packets
- est
->last_packets
) << (10 - est
->ewma_log
- est
->intvl_log
);
91 rate
-= (est
->avpps
>> est
->ewma_log
);
93 write_seqcount_begin(&est
->seq
);
96 write_seqcount_end(&est
->seq
);
98 est
->last_bytes
= b
.bytes
;
99 est
->last_packets
= b
.packets
;
101 est
->next_jiffies
+= ((HZ
/4) << est
->intvl_log
);
103 if (unlikely(time_after_eq(jiffies
, est
->next_jiffies
))) {
104 /* Ouch... timer was delayed. */
105 est
->next_jiffies
= jiffies
+ 1;
107 mod_timer(&est
->timer
, est
->next_jiffies
);
111 * gen_new_estimator - create a new rate estimator
112 * @bstats: basic statistics
113 * @cpu_bstats: bstats per cpu
114 * @rate_est: rate estimator statistics
115 * @lock: lock for statistics and control path
116 * @running: qdisc running seqcount
117 * @opt: rate estimator configuration TLV
119 * Creates a new rate estimator with &bstats as source and &rate_est
120 * as destination. A new timer with the interval specified in the
121 * configuration TLV is created. Upon each interval, the latest statistics
122 * will be read from &bstats and the estimated rate will be stored in
123 * &rate_est with the statistics lock grabbed during this period.
125 * Returns 0 on success or a negative error code.
128 int gen_new_estimator(struct gnet_stats_basic_packed
*bstats
,
129 struct gnet_stats_basic_cpu __percpu
*cpu_bstats
,
130 struct net_rate_estimator __rcu
**rate_est
,
135 struct gnet_estimator
*parm
= nla_data(opt
);
136 struct net_rate_estimator
*old
, *est
;
137 struct gnet_stats_basic_packed b
;
140 if (nla_len(opt
) < sizeof(*parm
))
143 /* allowed timer periods are :
144 * -2 : 250ms, -1 : 500ms, 0 : 1 sec
145 * 1 : 2 sec, 2 : 4 sec, 3 : 8 sec
147 if (parm
->interval
< -2 || parm
->interval
> 3)
150 est
= kzalloc(sizeof(*est
), GFP_KERNEL
);
154 seqcount_init(&est
->seq
);
155 intvl_log
= parm
->interval
+ 2;
156 est
->bstats
= bstats
;
157 est
->stats_lock
= lock
;
158 est
->running
= running
;
159 est
->ewma_log
= parm
->ewma_log
;
160 est
->intvl_log
= intvl_log
;
161 est
->cpu_bstats
= cpu_bstats
;
165 est_fetch_counters(est
, &b
);
168 est
->last_bytes
= b
.bytes
;
169 est
->last_packets
= b
.packets
;
173 old
= rcu_dereference_protected(*rate_est
, 1);
175 del_timer_sync(&old
->timer
);
176 est
->avbps
= old
->avbps
;
177 est
->avpps
= old
->avpps
;
180 est
->next_jiffies
= jiffies
+ ((HZ
/4) << intvl_log
);
181 timer_setup(&est
->timer
, est_timer
, 0);
182 mod_timer(&est
->timer
, est
->next_jiffies
);
184 rcu_assign_pointer(*rate_est
, est
);
186 spin_unlock_bh(lock
);
191 EXPORT_SYMBOL(gen_new_estimator
);
194 * gen_kill_estimator - remove a rate estimator
195 * @rate_est: rate estimator
197 * Removes the rate estimator.
200 void gen_kill_estimator(struct net_rate_estimator __rcu
**rate_est
)
202 struct net_rate_estimator
*est
;
204 est
= xchg((__force
struct net_rate_estimator
**)rate_est
, NULL
);
206 del_timer_sync(&est
->timer
);
210 EXPORT_SYMBOL(gen_kill_estimator
);
213 * gen_replace_estimator - replace rate estimator configuration
214 * @bstats: basic statistics
215 * @cpu_bstats: bstats per cpu
216 * @rate_est: rate estimator statistics
217 * @lock: lock for statistics and control path
218 * @running: qdisc running seqcount (might be NULL)
219 * @opt: rate estimator configuration TLV
221 * Replaces the configuration of a rate estimator by calling
222 * gen_kill_estimator() and gen_new_estimator().
224 * Returns 0 on success or a negative error code.
226 int gen_replace_estimator(struct gnet_stats_basic_packed
*bstats
,
227 struct gnet_stats_basic_cpu __percpu
*cpu_bstats
,
228 struct net_rate_estimator __rcu
**rate_est
,
230 seqcount_t
*running
, struct nlattr
*opt
)
232 return gen_new_estimator(bstats
, cpu_bstats
, rate_est
,
235 EXPORT_SYMBOL(gen_replace_estimator
);
238 * gen_estimator_active - test if estimator is currently in use
239 * @rate_est: rate estimator
241 * Returns true if estimator is active, and false if not.
243 bool gen_estimator_active(struct net_rate_estimator __rcu
**rate_est
)
245 return !!rcu_access_pointer(*rate_est
);
247 EXPORT_SYMBOL(gen_estimator_active
);
249 bool gen_estimator_read(struct net_rate_estimator __rcu
**rate_est
,
250 struct gnet_stats_rate_est64
*sample
)
252 struct net_rate_estimator
*est
;
256 est
= rcu_dereference(*rate_est
);
263 seq
= read_seqcount_begin(&est
->seq
);
264 sample
->bps
= est
->avbps
>> 8;
265 sample
->pps
= est
->avpps
>> 8;
266 } while (read_seqcount_retry(&est
->seq
, seq
));
271 EXPORT_SYMBOL(gen_estimator_read
);