aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Schillstrom <hans.schillstrom@ericsson.com>2011-01-03 08:44:54 -0500
committerSimon Horman <horms@verge.net.au>2011-01-12 20:30:28 -0500
commit29c2026fd4980c144d9c746dc1565060f08e5796 (patch)
tree37373a66fac997e01c83e774c21e00dca713598a
parentab8a5e8408c3df2d654611bffc3aaf04f418b266 (diff)
IPVS: netns awareness to ip_vs_est
All variables moved to struct ipvs, most external changes fixed (i.e. init_net removed) *v3 timer per ns instead of a common timer in estimator. Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--include/net/ip_vs.h4
-rw-r--r--include/net/netns/ip_vs.h4
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c20
-rw-r--r--net/netfilter/ipvs/ip_vs_est.c86
4 files changed, 64 insertions, 50 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 0cdd8ce454c2..c08927bb1728 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -1004,8 +1004,8 @@ extern void ip_vs_sync_cleanup(void);
1004 */ 1004 */
1005extern int ip_vs_estimator_init(void); 1005extern int ip_vs_estimator_init(void);
1006extern void ip_vs_estimator_cleanup(void); 1006extern void ip_vs_estimator_cleanup(void);
1007extern void ip_vs_new_estimator(struct ip_vs_stats *stats); 1007extern void ip_vs_new_estimator(struct net *net, struct ip_vs_stats *stats);
1008extern void ip_vs_kill_estimator(struct ip_vs_stats *stats); 1008extern void ip_vs_kill_estimator(struct net *net, struct ip_vs_stats *stats);
1009extern void ip_vs_zero_estimator(struct ip_vs_stats *stats); 1009extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
1010 1010
1011/* 1011/*
diff --git a/include/net/netns/ip_vs.h b/include/net/netns/ip_vs.h
index 03f7fe1bede6..db0240198339 100644
--- a/include/net/netns/ip_vs.h
+++ b/include/net/netns/ip_vs.h
@@ -70,6 +70,10 @@ struct netns_ipvs {
70 int sysctl_lblcr_expiration; 70 int sysctl_lblcr_expiration;
71 struct ctl_table_header *lblcr_ctl_header; 71 struct ctl_table_header *lblcr_ctl_header;
72 struct ctl_table *lblcr_ctl_table; 72 struct ctl_table *lblcr_ctl_table;
73 /* ip_vs_est */
74 struct list_head est_list; /* estimator list */
75 spinlock_t est_lock;
76 struct timer_list est_timer; /* Estimation timer */
73}; 77};
74 78
75#endif /* IP_VS_H_ */ 79#endif /* IP_VS_H_ */
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 88474f1e828a..c89beb8eafbb 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -816,7 +816,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
816 spin_unlock(&dest->dst_lock); 816 spin_unlock(&dest->dst_lock);
817 817
818 if (add) 818 if (add)
819 ip_vs_new_estimator(&dest->stats); 819 ip_vs_new_estimator(svc->net, &dest->stats);
820 820
821 write_lock_bh(&__ip_vs_svc_lock); 821 write_lock_bh(&__ip_vs_svc_lock);
822 822
@@ -1009,9 +1009,9 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
1009/* 1009/*
1010 * Delete a destination (must be already unlinked from the service) 1010 * Delete a destination (must be already unlinked from the service)
1011 */ 1011 */
1012static void __ip_vs_del_dest(struct ip_vs_dest *dest) 1012static void __ip_vs_del_dest(struct net *net, struct ip_vs_dest *dest)
1013{ 1013{
1014 ip_vs_kill_estimator(&dest->stats); 1014 ip_vs_kill_estimator(net, &dest->stats);
1015 1015
1016 /* 1016 /*
1017 * Remove it from the d-linked list with the real services. 1017 * Remove it from the d-linked list with the real services.
@@ -1080,6 +1080,7 @@ static int
1080ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) 1080ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
1081{ 1081{
1082 struct ip_vs_dest *dest; 1082 struct ip_vs_dest *dest;
1083 struct net *net = svc->net;
1083 __be16 dport = udest->port; 1084 __be16 dport = udest->port;
1084 1085
1085 EnterFunction(2); 1086 EnterFunction(2);
@@ -1108,7 +1109,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
1108 /* 1109 /*
1109 * Delete the destination 1110 * Delete the destination
1110 */ 1111 */
1111 __ip_vs_del_dest(dest); 1112 __ip_vs_del_dest(net, dest);
1112 1113
1113 LeaveFunction(2); 1114 LeaveFunction(2);
1114 1115
@@ -1197,7 +1198,7 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
1197 else if (svc->port == 0) 1198 else if (svc->port == 0)
1198 atomic_inc(&ip_vs_nullsvc_counter); 1199 atomic_inc(&ip_vs_nullsvc_counter);
1199 1200
1200 ip_vs_new_estimator(&svc->stats); 1201 ip_vs_new_estimator(net, &svc->stats);
1201 1202
1202 /* Count only IPv4 services for old get/setsockopt interface */ 1203 /* Count only IPv4 services for old get/setsockopt interface */
1203 if (svc->af == AF_INET) 1204 if (svc->af == AF_INET)
@@ -1345,7 +1346,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc)
1345 if (svc->af == AF_INET) 1346 if (svc->af == AF_INET)
1346 ip_vs_num_services--; 1347 ip_vs_num_services--;
1347 1348
1348 ip_vs_kill_estimator(&svc->stats); 1349 ip_vs_kill_estimator(svc->net, &svc->stats);
1349 1350
1350 /* Unbind scheduler */ 1351 /* Unbind scheduler */
1351 old_sched = svc->scheduler; 1352 old_sched = svc->scheduler;
@@ -1368,7 +1369,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc)
1368 */ 1369 */
1369 list_for_each_entry_safe(dest, nxt, &svc->destinations, n_list) { 1370 list_for_each_entry_safe(dest, nxt, &svc->destinations, n_list) {
1370 __ip_vs_unlink_dest(svc, dest, 0); 1371 __ip_vs_unlink_dest(svc, dest, 0);
1371 __ip_vs_del_dest(dest); 1372 __ip_vs_del_dest(svc->net, dest);
1372 } 1373 }
1373 1374
1374 /* 1375 /*
@@ -3460,7 +3461,7 @@ int __net_init __ip_vs_control_init(struct net *net)
3460 vs_vars); 3461 vs_vars);
3461 if (sysctl_header == NULL) 3462 if (sysctl_header == NULL)
3462 goto err_reg; 3463 goto err_reg;
3463 ip_vs_new_estimator(&ip_vs_stats); 3464 ip_vs_new_estimator(net, &ip_vs_stats);
3464 return 0; 3465 return 0;
3465 3466
3466err_reg: 3467err_reg:
@@ -3472,7 +3473,7 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net)
3472 if (!net_eq(net, &init_net)) /* netns not enabled yet */ 3473 if (!net_eq(net, &init_net)) /* netns not enabled yet */
3473 return; 3474 return;
3474 3475
3475 ip_vs_kill_estimator(&ip_vs_stats); 3476 ip_vs_kill_estimator(net, &ip_vs_stats);
3476 unregister_net_sysctl_table(sysctl_header); 3477 unregister_net_sysctl_table(sysctl_header);
3477 proc_net_remove(net, "ip_vs_stats"); 3478 proc_net_remove(net, "ip_vs_stats");
3478 proc_net_remove(net, "ip_vs"); 3479 proc_net_remove(net, "ip_vs");
@@ -3536,7 +3537,6 @@ void ip_vs_control_cleanup(void)
3536 ip_vs_trash_cleanup(); 3537 ip_vs_trash_cleanup();
3537 cancel_delayed_work_sync(&defense_work); 3538 cancel_delayed_work_sync(&defense_work);
3538 cancel_work_sync(&defense_work.work); 3539 cancel_work_sync(&defense_work.work);
3539 ip_vs_kill_estimator(&ip_vs_stats);
3540 unregister_pernet_subsys(&ipvs_control_ops); 3540 unregister_pernet_subsys(&ipvs_control_ops);
3541 ip_vs_genl_unregister(); 3541 ip_vs_genl_unregister();
3542 nf_unregister_sockopt(&ip_vs_sockopts); 3542 nf_unregister_sockopt(&ip_vs_sockopts);
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 7417a0c1408b..07d839bef537 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -8,8 +8,12 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 * 10 *
11 * Changes: 11 * Changes: Hans Schillstrom <hans.schillstrom@ericsson.com>
12 * 12 * Network name space (netns) aware.
13 * Global data moved to netns i.e struct netns_ipvs
14 * Affected data: est_list and est_lock.
15 * estimation_timer() runs with timer per netns.
16 * get_stats()) do the per cpu summing.
13 */ 17 */
14 18
15#define KMSG_COMPONENT "IPVS" 19#define KMSG_COMPONENT "IPVS"
@@ -48,12 +52,6 @@
48 */ 52 */
49 53
50 54
51static void estimation_timer(unsigned long arg);
52
53static LIST_HEAD(est_list);
54static DEFINE_SPINLOCK(est_lock);
55static DEFINE_TIMER(est_timer, estimation_timer, 0, 0);
56
57static void estimation_timer(unsigned long arg) 55static void estimation_timer(unsigned long arg)
58{ 56{
59 struct ip_vs_estimator *e; 57 struct ip_vs_estimator *e;
@@ -62,9 +60,12 @@ static void estimation_timer(unsigned long arg)
62 u32 n_inpkts, n_outpkts; 60 u32 n_inpkts, n_outpkts;
63 u64 n_inbytes, n_outbytes; 61 u64 n_inbytes, n_outbytes;
64 u32 rate; 62 u32 rate;
63 struct net *net = (struct net *)arg;
64 struct netns_ipvs *ipvs;
65 65
66 spin_lock(&est_lock); 66 ipvs = net_ipvs(net);
67 list_for_each_entry(e, &est_list, list) { 67 spin_lock(&ipvs->est_lock);
68 list_for_each_entry(e, &ipvs->est_list, list) {
68 s = container_of(e, struct ip_vs_stats, est); 69 s = container_of(e, struct ip_vs_stats, est);
69 70
70 spin_lock(&s->lock); 71 spin_lock(&s->lock);
@@ -75,38 +76,39 @@ static void estimation_timer(unsigned long arg)
75 n_outbytes = s->ustats.outbytes; 76 n_outbytes = s->ustats.outbytes;
76 77
77 /* scaled by 2^10, but divided 2 seconds */ 78 /* scaled by 2^10, but divided 2 seconds */
78 rate = (n_conns - e->last_conns)<<9; 79 rate = (n_conns - e->last_conns) << 9;
79 e->last_conns = n_conns; 80 e->last_conns = n_conns;
80 e->cps += ((long)rate - (long)e->cps)>>2; 81 e->cps += ((long)rate - (long)e->cps) >> 2;
81 s->ustats.cps = (e->cps+0x1FF)>>10; 82 s->ustats.cps = (e->cps + 0x1FF) >> 10;
82 83
83 rate = (n_inpkts - e->last_inpkts)<<9; 84 rate = (n_inpkts - e->last_inpkts) << 9;
84 e->last_inpkts = n_inpkts; 85 e->last_inpkts = n_inpkts;
85 e->inpps += ((long)rate - (long)e->inpps)>>2; 86 e->inpps += ((long)rate - (long)e->inpps) >> 2;
86 s->ustats.inpps = (e->inpps+0x1FF)>>10; 87 s->ustats.inpps = (e->inpps + 0x1FF) >> 10;
87 88
88 rate = (n_outpkts - e->last_outpkts)<<9; 89 rate = (n_outpkts - e->last_outpkts) << 9;
89 e->last_outpkts = n_outpkts; 90 e->last_outpkts = n_outpkts;
90 e->outpps += ((long)rate - (long)e->outpps)>>2; 91 e->outpps += ((long)rate - (long)e->outpps) >> 2;
91 s->ustats.outpps = (e->outpps+0x1FF)>>10; 92 s->ustats.outpps = (e->outpps + 0x1FF) >> 10;
92 93
93 rate = (n_inbytes - e->last_inbytes)<<4; 94 rate = (n_inbytes - e->last_inbytes) << 4;
94 e->last_inbytes = n_inbytes; 95 e->last_inbytes = n_inbytes;
95 e->inbps += ((long)rate - (long)e->inbps)>>2; 96 e->inbps += ((long)rate - (long)e->inbps) >> 2;
96 s->ustats.inbps = (e->inbps+0xF)>>5; 97 s->ustats.inbps = (e->inbps + 0xF) >> 5;
97 98
98 rate = (n_outbytes - e->last_outbytes)<<4; 99 rate = (n_outbytes - e->last_outbytes) << 4;
99 e->last_outbytes = n_outbytes; 100 e->last_outbytes = n_outbytes;
100 e->outbps += ((long)rate - (long)e->outbps)>>2; 101 e->outbps += ((long)rate - (long)e->outbps) >> 2;
101 s->ustats.outbps = (e->outbps+0xF)>>5; 102 s->ustats.outbps = (e->outbps + 0xF) >> 5;
102 spin_unlock(&s->lock); 103 spin_unlock(&s->lock);
103 } 104 }
104 spin_unlock(&est_lock); 105 spin_unlock(&ipvs->est_lock);
105 mod_timer(&est_timer, jiffies + 2*HZ); 106 mod_timer(&ipvs->est_timer, jiffies + 2*HZ);
106} 107}
107 108
108void ip_vs_new_estimator(struct ip_vs_stats *stats) 109void ip_vs_new_estimator(struct net *net, struct ip_vs_stats *stats)
109{ 110{
111 struct netns_ipvs *ipvs = net_ipvs(net);
110 struct ip_vs_estimator *est = &stats->est; 112 struct ip_vs_estimator *est = &stats->est;
111 113
112 INIT_LIST_HEAD(&est->list); 114 INIT_LIST_HEAD(&est->list);
@@ -126,18 +128,19 @@ void ip_vs_new_estimator(struct ip_vs_stats *stats)
126 est->last_outbytes = stats->ustats.outbytes; 128 est->last_outbytes = stats->ustats.outbytes;
127 est->outbps = stats->ustats.outbps<<5; 129 est->outbps = stats->ustats.outbps<<5;
128 130
129 spin_lock_bh(&est_lock); 131 spin_lock_bh(&ipvs->est_lock);
130 list_add(&est->list, &est_list); 132 list_add(&est->list, &ipvs->est_list);
131 spin_unlock_bh(&est_lock); 133 spin_unlock_bh(&ipvs->est_lock);
132} 134}
133 135
134void ip_vs_kill_estimator(struct ip_vs_stats *stats) 136void ip_vs_kill_estimator(struct net *net, struct ip_vs_stats *stats)
135{ 137{
138 struct netns_ipvs *ipvs = net_ipvs(net);
136 struct ip_vs_estimator *est = &stats->est; 139 struct ip_vs_estimator *est = &stats->est;
137 140
138 spin_lock_bh(&est_lock); 141 spin_lock_bh(&ipvs->est_lock);
139 list_del(&est->list); 142 list_del(&est->list);
140 spin_unlock_bh(&est_lock); 143 spin_unlock_bh(&ipvs->est_lock);
141} 144}
142 145
143void ip_vs_zero_estimator(struct ip_vs_stats *stats) 146void ip_vs_zero_estimator(struct ip_vs_stats *stats)
@@ -159,14 +162,25 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats)
159 162
160static int __net_init __ip_vs_estimator_init(struct net *net) 163static int __net_init __ip_vs_estimator_init(struct net *net)
161{ 164{
165 struct netns_ipvs *ipvs = net_ipvs(net);
166
162 if (!net_eq(net, &init_net)) /* netns not enabled yet */ 167 if (!net_eq(net, &init_net)) /* netns not enabled yet */
163 return -EPERM; 168 return -EPERM;
164 169
170 INIT_LIST_HEAD(&ipvs->est_list);
171 spin_lock_init(&ipvs->est_lock);
172 setup_timer(&ipvs->est_timer, estimation_timer, (unsigned long)net);
173 mod_timer(&ipvs->est_timer, jiffies + 2 * HZ);
165 return 0; 174 return 0;
166} 175}
167 176
177static void __net_exit __ip_vs_estimator_exit(struct net *net)
178{
179 del_timer_sync(&net_ipvs(net)->est_timer);
180}
168static struct pernet_operations ip_vs_app_ops = { 181static struct pernet_operations ip_vs_app_ops = {
169 .init = __ip_vs_estimator_init, 182 .init = __ip_vs_estimator_init,
183 .exit = __ip_vs_estimator_exit,
170}; 184};
171 185
172int __init ip_vs_estimator_init(void) 186int __init ip_vs_estimator_init(void)
@@ -174,14 +188,10 @@ int __init ip_vs_estimator_init(void)
174 int rv; 188 int rv;
175 189
176 rv = register_pernet_subsys(&ip_vs_app_ops); 190 rv = register_pernet_subsys(&ip_vs_app_ops);
177 if (rv < 0)
178 return rv;
179 mod_timer(&est_timer, jiffies + 2 * HZ);
180 return rv; 191 return rv;
181} 192}
182 193
183void ip_vs_estimator_cleanup(void) 194void ip_vs_estimator_cleanup(void)
184{ 195{
185 del_timer_sync(&est_timer);
186 unregister_pernet_subsys(&ip_vs_app_ops); 196 unregister_pernet_subsys(&ip_vs_app_ops);
187} 197}