]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - net/ipv4/ipvs/ip_vs_est.c
ipvs: Mark net_vs_ctl_path const
[mirror_ubuntu-artful-kernel.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>
1da177e4
LT
20
21#include <net/ip_vs.h>
22
23/*
24 This code is to estimate rate in a shorter interval (such as 8
25 seconds) for virtual services and real servers. For measure rate in a
26 long interval, it is easy to implement a user level daemon which
27 periodically reads those statistical counters and measure rate.
28
29 Currently, the measurement is activated by slow timer handler. Hope
30 this measurement will not introduce too much load.
31
32 We measure rate during the last 8 seconds every 2 seconds:
33
34 avgrate = avgrate*(1-W) + rate*W
35
36 where W = 2^(-2)
37
38 NOTES.
39
40 * The stored value for average bps is scaled by 2^5, so that maximal
41 rate is ~2.15Gbits/s, average pps and cps are scaled by 2^10.
42
43 * A lot code is taken from net/sched/estimator.c
44 */
45
46
47struct ip_vs_estimator
48{
49 struct ip_vs_estimator *next;
50 struct ip_vs_stats *stats;
51
52 u32 last_conns;
53 u32 last_inpkts;
54 u32 last_outpkts;
55 u64 last_inbytes;
56 u64 last_outbytes;
57
58 u32 cps;
59 u32 inpps;
60 u32 outpps;
61 u32 inbps;
62 u32 outbps;
63};
64
65
66static struct ip_vs_estimator *est_list = NULL;
67static DEFINE_RWLOCK(est_lock);
68static struct timer_list est_timer;
69
70static void estimation_timer(unsigned long arg)
71{
72 struct ip_vs_estimator *e;
73 struct ip_vs_stats *s;
74 u32 n_conns;
75 u32 n_inpkts, n_outpkts;
76 u64 n_inbytes, n_outbytes;
77 u32 rate;
78
79 read_lock(&est_lock);
80 for (e = est_list; e; e = e->next) {
81 s = e->stats;
82
83 spin_lock(&s->lock);
84 n_conns = s->conns;
85 n_inpkts = s->inpkts;
86 n_outpkts = s->outpkts;
87 n_inbytes = s->inbytes;
88 n_outbytes = s->outbytes;
89
90 /* scaled by 2^10, but divided 2 seconds */
91 rate = (n_conns - e->last_conns)<<9;
92 e->last_conns = n_conns;
93 e->cps += ((long)rate - (long)e->cps)>>2;
94 s->cps = (e->cps+0x1FF)>>10;
95
96 rate = (n_inpkts - e->last_inpkts)<<9;
97 e->last_inpkts = n_inpkts;
98 e->inpps += ((long)rate - (long)e->inpps)>>2;
99 s->inpps = (e->inpps+0x1FF)>>10;
100
101 rate = (n_outpkts - e->last_outpkts)<<9;
102 e->last_outpkts = n_outpkts;
103 e->outpps += ((long)rate - (long)e->outpps)>>2;
104 s->outpps = (e->outpps+0x1FF)>>10;
105
106 rate = (n_inbytes - e->last_inbytes)<<4;
107 e->last_inbytes = n_inbytes;
108 e->inbps += ((long)rate - (long)e->inbps)>>2;
109 s->inbps = (e->inbps+0xF)>>5;
110
111 rate = (n_outbytes - e->last_outbytes)<<4;
112 e->last_outbytes = n_outbytes;
113 e->outbps += ((long)rate - (long)e->outbps)>>2;
114 s->outbps = (e->outbps+0xF)>>5;
115 spin_unlock(&s->lock);
116 }
117 read_unlock(&est_lock);
118 mod_timer(&est_timer, jiffies + 2*HZ);
119}
120
121int ip_vs_new_estimator(struct ip_vs_stats *stats)
122{
123 struct ip_vs_estimator *est;
124
0da974f4 125 est = kzalloc(sizeof(*est), GFP_KERNEL);
1da177e4
LT
126 if (est == NULL)
127 return -ENOMEM;
128
1da177e4
LT
129 est->stats = stats;
130 est->last_conns = stats->conns;
131 est->cps = stats->cps<<10;
132
133 est->last_inpkts = stats->inpkts;
134 est->inpps = stats->inpps<<10;
135
136 est->last_outpkts = stats->outpkts;
137 est->outpps = stats->outpps<<10;
138
139 est->last_inbytes = stats->inbytes;
140 est->inbps = stats->inbps<<5;
141
142 est->last_outbytes = stats->outbytes;
143 est->outbps = stats->outbps<<5;
144
145 write_lock_bh(&est_lock);
146 est->next = est_list;
147 if (est->next == NULL) {
b24b8a24 148 setup_timer(&est_timer, estimation_timer, 0);
1da177e4 149 est_timer.expires = jiffies + 2*HZ;
1da177e4
LT
150 add_timer(&est_timer);
151 }
152 est_list = est;
153 write_unlock_bh(&est_lock);
154 return 0;
155}
156
157void ip_vs_kill_estimator(struct ip_vs_stats *stats)
158{
159 struct ip_vs_estimator *est, **pest;
160 int killed = 0;
161
162 write_lock_bh(&est_lock);
163 pest = &est_list;
164 while ((est=*pest) != NULL) {
165 if (est->stats != stats) {
166 pest = &est->next;
167 continue;
168 }
169 *pest = est->next;
170 kfree(est);
171 killed++;
172 }
8ab19ea3
SW
173 while (killed && !est_list && try_to_del_timer_sync(&est_timer) < 0) {
174 write_unlock_bh(&est_lock);
175 cpu_relax();
176 write_lock_bh(&est_lock);
177 }
1da177e4
LT
178 write_unlock_bh(&est_lock);
179}
180
181void ip_vs_zero_estimator(struct ip_vs_stats *stats)
182{
183 struct ip_vs_estimator *e;
184
185 write_lock_bh(&est_lock);
186 for (e = est_list; e; e = e->next) {
187 if (e->stats != stats)
188 continue;
189
190 /* set counters zero */
191 e->last_conns = 0;
192 e->last_inpkts = 0;
193 e->last_outpkts = 0;
194 e->last_inbytes = 0;
195 e->last_outbytes = 0;
196 e->cps = 0;
197 e->inpps = 0;
198 e->outpps = 0;
199 e->inbps = 0;
200 e->outbps = 0;
201 }
202 write_unlock_bh(&est_lock);
203}