ipvs: Embed estimator object into stats object
[deliverable/linux.git] / net / ipv4 / ipvs / ip_vs_est.c
CommitLineData
1da177e4
LT
1/*
2 * ip_vs_est.c: simple rate estimator for IPVS
3 *
1da177e4
LT
4 * Authors: Wensong Zhang <wensong@linuxvirtualserver.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 * Changes:
12 *
13 */
14#include <linux/kernel.h>
14c85021
ACM
15#include <linux/jiffies.h>
16#include <linux/slab.h>
1da177e4 17#include <linux/types.h>
4ffd2e49 18#include <linux/interrupt.h>
90754f8e 19#include <linux/sysctl.h>
3a14a313 20#include <linux/list.h>
1da177e4
LT
21
22#include <net/ip_vs.h>
23
24/*
25 This code is to estimate rate in a shorter interval (such as 8
26 seconds) for virtual services and real servers. For measure rate in a
27 long interval, it is easy to implement a user level daemon which
28 periodically reads those statistical counters and measure rate.
29
30 Currently, the measurement is activated by slow timer handler. Hope
31 this measurement will not introduce too much load.
32
33 We measure rate during the last 8 seconds every 2 seconds:
34
35 avgrate = avgrate*(1-W) + rate*W
36
37 where W = 2^(-2)
38
39 NOTES.
40
41 * The stored value for average bps is scaled by 2^5, so that maximal
42 rate is ~2.15Gbits/s, average pps and cps are scaled by 2^10.
43
44 * A lot code is taken from net/sched/estimator.c
45 */
46
47
3a14a313 48static void estimation_timer(unsigned long arg);
1da177e4 49
3a14a313
SW
50static LIST_HEAD(est_list);
51static DEFINE_SPINLOCK(est_lock);
52static DEFINE_TIMER(est_timer, estimation_timer, 0, 0);
1da177e4
LT
53
54static void estimation_timer(unsigned long arg)
55{
56 struct ip_vs_estimator *e;
57 struct ip_vs_stats *s;
58 u32 n_conns;
59 u32 n_inpkts, n_outpkts;
60 u64 n_inbytes, n_outbytes;
61 u32 rate;
62
3a14a313
SW
63 spin_lock(&est_lock);
64 list_for_each_entry(e, &est_list, list) {
65 s = container_of(e, struct ip_vs_stats, est);
1da177e4
LT
66
67 spin_lock(&s->lock);
68 n_conns = s->conns;
69 n_inpkts = s->inpkts;
70 n_outpkts = s->outpkts;
71 n_inbytes = s->inbytes;
72 n_outbytes = s->outbytes;
73
74 /* scaled by 2^10, but divided 2 seconds */
75 rate = (n_conns - e->last_conns)<<9;
76 e->last_conns = n_conns;
77 e->cps += ((long)rate - (long)e->cps)>>2;
78 s->cps = (e->cps+0x1FF)>>10;
79
80 rate = (n_inpkts - e->last_inpkts)<<9;
81 e->last_inpkts = n_inpkts;
82 e->inpps += ((long)rate - (long)e->inpps)>>2;
83 s->inpps = (e->inpps+0x1FF)>>10;
84
85 rate = (n_outpkts - e->last_outpkts)<<9;
86 e->last_outpkts = n_outpkts;
87 e->outpps += ((long)rate - (long)e->outpps)>>2;
88 s->outpps = (e->outpps+0x1FF)>>10;
89
90 rate = (n_inbytes - e->last_inbytes)<<4;
91 e->last_inbytes = n_inbytes;
92 e->inbps += ((long)rate - (long)e->inbps)>>2;
93 s->inbps = (e->inbps+0xF)>>5;
94
95 rate = (n_outbytes - e->last_outbytes)<<4;
96 e->last_outbytes = n_outbytes;
97 e->outbps += ((long)rate - (long)e->outbps)>>2;
98 s->outbps = (e->outbps+0xF)>>5;
99 spin_unlock(&s->lock);
100 }
3a14a313 101 spin_unlock(&est_lock);
1da177e4
LT
102 mod_timer(&est_timer, jiffies + 2*HZ);
103}
104
3a14a313 105void ip_vs_new_estimator(struct ip_vs_stats *stats)
1da177e4 106{
3a14a313 107 struct ip_vs_estimator *est = &stats->est;
1da177e4 108
3a14a313 109 INIT_LIST_HEAD(&est->list);
1da177e4 110
1da177e4
LT
111 est->last_conns = stats->conns;
112 est->cps = stats->cps<<10;
113
114 est->last_inpkts = stats->inpkts;
115 est->inpps = stats->inpps<<10;
116
117 est->last_outpkts = stats->outpkts;
118 est->outpps = stats->outpps<<10;
119
120 est->last_inbytes = stats->inbytes;
121 est->inbps = stats->inbps<<5;
122
123 est->last_outbytes = stats->outbytes;
124 est->outbps = stats->outbps<<5;
125
3a14a313
SW
126 spin_lock_bh(&est_lock);
127 if (list_empty(&est_list))
128 mod_timer(&est_timer, jiffies + 2 * HZ);
129 list_add(&est->list, &est_list);
130 spin_unlock_bh(&est_lock);
1da177e4
LT
131}
132
133void ip_vs_kill_estimator(struct ip_vs_stats *stats)
134{
3a14a313
SW
135 struct ip_vs_estimator *est = &stats->est;
136
137 spin_lock_bh(&est_lock);
138 list_del(&est->list);
139 while (list_empty(&est_list) && try_to_del_timer_sync(&est_timer) < 0) {
140 spin_unlock_bh(&est_lock);
8ab19ea3 141 cpu_relax();
3a14a313 142 spin_lock_bh(&est_lock);
8ab19ea3 143 }
3a14a313 144 spin_unlock_bh(&est_lock);
1da177e4
LT
145}
146
147void ip_vs_zero_estimator(struct ip_vs_stats *stats)
148{
3a14a313
SW
149 struct ip_vs_estimator *est = &stats->est;
150
151 /* set counters zero, caller must hold the stats->lock lock */
152 est->last_inbytes = 0;
153 est->last_outbytes = 0;
154 est->last_conns = 0;
155 est->last_inpkts = 0;
156 est->last_outpkts = 0;
157 est->cps = 0;
158 est->inpps = 0;
159 est->outpps = 0;
160 est->inbps = 0;
161 est->outbps = 0;
1da177e4 162}
This page took 0.384311 seconds and 5 git commands to generate.