Blame view

net/netfilter/ipvs/ip_vs_conn.c 36.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   * IPVS         An implementation of the IP virtual server support for the
   *              LINUX operating system.  IPVS is now implemented as a module
   *              over the Netfilter framework. IPVS can be used to build a
   *              high-performance and highly available server based on a
   *              cluster of servers.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
   *              Peter Kese <peter.kese@ijs.si>
   *              Julian Anastasov <ja@ssi.bg>
   *
   *              This program is free software; you can redistribute it and/or
   *              modify it under the terms of the GNU General Public License
   *              as published by the Free Software Foundation; either version
   *              2 of the License, or (at your option) any later version.
   *
   * The IPVS code for kernel 2.2 was done by Wensong Zhang and Peter Kese,
   * with changes/fixes from Julian Anastasov, Lars Marowsky-Bree, Horms
   * and others. Many code here is taken from IP MASQ code of kernel 2.2.
   *
   * Changes:
   *
   */
9aada7ac0   Hannes Eder   IPVS: use pr_fmt
24
25
  #define KMSG_COMPONENT "IPVS"
  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
e924283bf   Andrew Morton   [IPVS]: Another f...
26
  #include <linux/interrupt.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
27
  #include <linux/in.h>
f18ae7206   Julian Anastasov   ipvs: use the new...
28
  #include <linux/inet.h>
f190055ff   Arnaldo Carvalho de Melo   [IPVS]: Add missi...
29
  #include <linux/net.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include <linux/kernel.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
31
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  #include <linux/vmalloc.h>
  #include <linux/proc_fs.h>		/* for proc_net_* */
5a0e3ad6a   Tejun Heo   include cleanup: ...
34
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
  #include <linux/seq_file.h>
  #include <linux/jhash.h>
  #include <linux/random.h>
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
38
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  #include <net/ip_vs.h>
6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
40
41
42
43
44
45
46
  #ifndef CONFIG_IP_VS_TAB_BITS
  #define CONFIG_IP_VS_TAB_BITS	12
  #endif
  
  /*
   * Connection hash size. Default is what was selected at compile time.
  */
4ecd29447   Eric Dumazet   ipvs: add static ...
47
  static int ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS;
6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
48
49
50
51
  module_param_named(conn_tab_bits, ip_vs_conn_tab_bits, int, 0444);
  MODULE_PARM_DESC(conn_tab_bits, "Set connections' hash size");
  
  /* size and mask values */
4ecd29447   Eric Dumazet   ipvs: add static ...
52
53
  int ip_vs_conn_tab_size __read_mostly;
  static int ip_vs_conn_tab_mask __read_mostly;
6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
54

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
  /*
   *  Connection hash table: for input and output packets lookups of IPVS
   */
731109e78   Changli Gao   ipvs: use hlist i...
58
  static struct hlist_head *ip_vs_conn_tab __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
  
  /*  SLAB cache for IPVS connections */
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
61
  static struct kmem_cache *ip_vs_conn_cachep __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
  /*  counter for no client port connections */
  static atomic_t ip_vs_conn_no_cport_cnt = ATOMIC_INIT(0);
  
  /* random value for IPVS connection hash */
4ecd29447   Eric Dumazet   ipvs: add static ...
67
  static unsigned int ip_vs_conn_rnd __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
71
  
  /*
   *  Fine locking granularity for big connection hash table
   */
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
72
  #define CT_LOCKARRAY_BITS  5
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
  #define CT_LOCKARRAY_SIZE  (1<<CT_LOCKARRAY_BITS)
  #define CT_LOCKARRAY_MASK  (CT_LOCKARRAY_SIZE-1)
f18ae7206   Julian Anastasov   ipvs: use the new...
75
76
77
78
79
80
  /* We need an addrstrlen that works with or without v6 */
  #ifdef CONFIG_IP_VS_IPV6
  #define IP_VS_ADDRSTRLEN INET6_ADDRSTRLEN
  #else
  #define IP_VS_ADDRSTRLEN (8+1)
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
  struct ip_vs_aligned_lock
  {
088339a57   Julian Anastasov   ipvs: convert con...
83
  	spinlock_t	l;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
  } __attribute__((__aligned__(SMP_CACHE_BYTES)));
  
  /* lock array for conn table */
  static struct ip_vs_aligned_lock
  __ip_vs_conntbl_lock_array[CT_LOCKARRAY_SIZE] __cacheline_aligned;
ac69269a4   Julian Anastasov   ipvs: do not disa...
89
  static inline void ct_write_lock_bh(unsigned int key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  {
ac69269a4   Julian Anastasov   ipvs: do not disa...
91
  	spin_lock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  }
ac69269a4   Julian Anastasov   ipvs: do not disa...
93
  static inline void ct_write_unlock_bh(unsigned int key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  {
ac69269a4   Julian Anastasov   ipvs: do not disa...
95
  	spin_unlock_bh(&__ip_vs_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  }
013b04246   Marco Angaroni   ipvs: optimize re...
97
  static void ip_vs_conn_expire(unsigned long data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
  
  /*
   *	Returns hash value for IPVS connection entry
   */
754b81a35   Eric W. Biederman   ipvs: Pass ipvs n...
102
  static unsigned int ip_vs_conn_hashkey(struct netns_ipvs *ipvs, int af, unsigned int proto,
28364a59f   Julius Volz   IPVS: Extend func...
103
104
  				       const union nf_inet_addr *addr,
  				       __be16 port)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  {
28364a59f   Julius Volz   IPVS: Extend func...
106
107
  #ifdef CONFIG_IP_VS_IPV6
  	if (af == AF_INET6)
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
108
109
  		return (jhash_3words(jhash(addr, 16, ip_vs_conn_rnd),
  				    (__force u32)port, proto, ip_vs_conn_rnd) ^
754b81a35   Eric W. Biederman   ipvs: Pass ipvs n...
110
  			((size_t)ipvs>>8)) & ip_vs_conn_tab_mask;
28364a59f   Julius Volz   IPVS: Extend func...
111
  #endif
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
112
113
  	return (jhash_3words((__force u32)addr->ip, (__force u32)port, proto,
  			    ip_vs_conn_rnd) ^
754b81a35   Eric W. Biederman   ipvs: Pass ipvs n...
114
  		((size_t)ipvs>>8)) & ip_vs_conn_tab_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  }
85999283a   Simon Horman   IPVS: Add struct ...
116
117
118
119
120
  static unsigned int ip_vs_conn_hashkey_param(const struct ip_vs_conn_param *p,
  					     bool inverse)
  {
  	const union nf_inet_addr *addr;
  	__be16 port;
f71499aa1   Simon Horman   IPVS: Fallback if...
121
  	if (p->pe_data && p->pe->hashkey_raw)
85999283a   Simon Horman   IPVS: Add struct ...
122
123
124
125
126
127
128
129
130
131
  		return p->pe->hashkey_raw(p, ip_vs_conn_rnd, inverse) &
  			ip_vs_conn_tab_mask;
  
  	if (likely(!inverse)) {
  		addr = p->caddr;
  		port = p->cport;
  	} else {
  		addr = p->vaddr;
  		port = p->vport;
  	}
754b81a35   Eric W. Biederman   ipvs: Pass ipvs n...
132
  	return ip_vs_conn_hashkey(p->ipvs, p->af, p->protocol, addr, port);
85999283a   Simon Horman   IPVS: Add struct ...
133
134
135
136
137
  }
  
  static unsigned int ip_vs_conn_hashkey_conn(const struct ip_vs_conn *cp)
  {
  	struct ip_vs_conn_param p;
19913dec1   Eric W. Biederman   ipvs: Pass ipvs n...
138
  	ip_vs_conn_fill_param(cp->ipvs, cp->af, cp->protocol,
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
139
  			      &cp->caddr, cp->cport, NULL, 0, &p);
85999283a   Simon Horman   IPVS: Add struct ...
140

e9e5eee87   Simon Horman   IPVS: Add persist...
141
142
  	if (cp->pe) {
  		p.pe = cp->pe;
85999283a   Simon Horman   IPVS: Add struct ...
143
144
145
146
147
148
  		p.pe_data = cp->pe_data;
  		p.pe_data_len = cp->pe_data_len;
  	}
  
  	return ip_vs_conn_hashkey_param(&p, false);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
  
  /*
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
151
   *	Hashes ip_vs_conn in ip_vs_conn_tab by netns,proto,addr,port.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
   *	returns bool success.
   */
  static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
  {
95c961747   Eric Dumazet   net: cleanup unsi...
156
  	unsigned int hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  	int ret;
26ec037f9   Nick Chalk   IPVS: one-packet ...
158
159
  	if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
  	/* Hash by protocol, client address and port */
85999283a   Simon Horman   IPVS: Add struct ...
161
  	hash = ip_vs_conn_hashkey_conn(cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162

ac69269a4   Julian Anastasov   ipvs: do not disa...
163
  	ct_write_lock_bh(hash);
aea9d711f   Sven Wegener   ipvs: Add missing...
164
  	spin_lock(&cp->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
  
  	if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
  		cp->flags |= IP_VS_CONN_F_HASHED;
  		atomic_inc(&cp->refcnt);
088339a57   Julian Anastasov   ipvs: convert con...
169
  		hlist_add_head_rcu(&cp->c_list, &ip_vs_conn_tab[hash]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
  		ret = 1;
  	} else {
1e3e238e9   Hannes Eder   IPVS: use pr_err ...
172
173
174
  		pr_err("%s(): request for already hashed, called from %pF
  ",
  		       __func__, __builtin_return_address(0));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
  		ret = 0;
  	}
aea9d711f   Sven Wegener   ipvs: Add missing...
177
  	spin_unlock(&cp->lock);
ac69269a4   Julian Anastasov   ipvs: do not disa...
178
  	ct_write_unlock_bh(hash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
181
182
183
184
185
  
  	return ret;
  }
  
  
  /*
   *	UNhashes ip_vs_conn from ip_vs_conn_tab.
088339a57   Julian Anastasov   ipvs: convert con...
186
   *	returns bool success. Caller should hold conn reference.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
   */
  static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
  {
95c961747   Eric Dumazet   net: cleanup unsi...
190
  	unsigned int hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
193
  	int ret;
  
  	/* unhash it and decrease its reference counter */
85999283a   Simon Horman   IPVS: Add struct ...
194
  	hash = ip_vs_conn_hashkey_conn(cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195

ac69269a4   Julian Anastasov   ipvs: do not disa...
196
  	ct_write_lock_bh(hash);
aea9d711f   Sven Wegener   ipvs: Add missing...
197
  	spin_lock(&cp->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
  
  	if (cp->flags & IP_VS_CONN_F_HASHED) {
088339a57   Julian Anastasov   ipvs: convert con...
200
  		hlist_del_rcu(&cp->c_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
  		cp->flags &= ~IP_VS_CONN_F_HASHED;
  		atomic_dec(&cp->refcnt);
  		ret = 1;
  	} else
  		ret = 0;
aea9d711f   Sven Wegener   ipvs: Add missing...
206
  	spin_unlock(&cp->lock);
ac69269a4   Julian Anastasov   ipvs: do not disa...
207
  	ct_write_unlock_bh(hash);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
  
  	return ret;
  }
088339a57   Julian Anastasov   ipvs: convert con...
211
212
213
214
215
216
217
218
219
  /* Try to unlink ip_vs_conn from ip_vs_conn_tab.
   * returns bool success.
   */
  static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
  {
  	unsigned int hash;
  	bool ret;
  
  	hash = ip_vs_conn_hashkey_conn(cp);
ac69269a4   Julian Anastasov   ipvs: do not disa...
220
  	ct_write_lock_bh(hash);
088339a57   Julian Anastasov   ipvs: convert con...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  	spin_lock(&cp->lock);
  
  	if (cp->flags & IP_VS_CONN_F_HASHED) {
  		ret = false;
  		/* Decrease refcnt and unlink conn only if we are last user */
  		if (atomic_cmpxchg(&cp->refcnt, 1, 0) == 1) {
  			hlist_del_rcu(&cp->c_list);
  			cp->flags &= ~IP_VS_CONN_F_HASHED;
  			ret = true;
  		}
  	} else
  		ret = atomic_read(&cp->refcnt) ? false : true;
  
  	spin_unlock(&cp->lock);
ac69269a4   Julian Anastasov   ipvs: do not disa...
235
  	ct_write_unlock_bh(hash);
088339a57   Julian Anastasov   ipvs: convert con...
236
237
238
  
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
  
  /*
   *  Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
   *  Called for pkts coming from OUTside-to-INside.
f11017ec2   Simon Horman   IPVS: Add struct ...
243
244
   *	p->caddr, p->cport: pkt source address (foreign host)
   *	p->vaddr, p->vport: pkt dest address (load balancer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
   */
f11017ec2   Simon Horman   IPVS: Add struct ...
246
247
  static inline struct ip_vs_conn *
  __ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  {
95c961747   Eric Dumazet   net: cleanup unsi...
249
  	unsigned int hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  	struct ip_vs_conn *cp;
85999283a   Simon Horman   IPVS: Add struct ...
251
  	hash = ip_vs_conn_hashkey_param(p, false);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

088339a57   Julian Anastasov   ipvs: convert con...
253
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

088339a57   Julian Anastasov   ipvs: convert con...
255
  	hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
1845ed0bb   Julian Anastasov   ipvs: reorder key...
256
257
  		if (p->cport == cp->cport && p->vport == cp->vport &&
  		    cp->af == p->af &&
f11017ec2   Simon Horman   IPVS: Add struct ...
258
259
  		    ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
  		    ip_vs_addr_equal(p->af, p->vaddr, &cp->vaddr) &&
f11017ec2   Simon Horman   IPVS: Add struct ...
260
  		    ((!p->cport) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
261
  		    p->protocol == cp->protocol &&
e64e2b460   Eric W. Biederman   ipvs: Store ipvs ...
262
  		    cp->ipvs == p->ipvs) {
088339a57   Julian Anastasov   ipvs: convert con...
263
264
  			if (!__ip_vs_conn_get(cp))
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  			/* HIT */
088339a57   Julian Anastasov   ipvs: convert con...
266
  			rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
  			return cp;
  		}
  	}
088339a57   Julian Anastasov   ipvs: convert con...
270
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
  
  	return NULL;
  }
f11017ec2   Simon Horman   IPVS: Add struct ...
274
  struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
  {
  	struct ip_vs_conn *cp;
f11017ec2   Simon Horman   IPVS: Add struct ...
277
278
279
280
281
282
  	cp = __ip_vs_conn_in_get(p);
  	if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt)) {
  		struct ip_vs_conn_param cport_zero_p = *p;
  		cport_zero_p.cport = 0;
  		cp = __ip_vs_conn_in_get(&cport_zero_p);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283

28364a59f   Julius Volz   IPVS: Extend func...
284
285
  	IP_VS_DBG_BUF(9, "lookup/in %s %s:%d->%s:%d %s
  ",
f11017ec2   Simon Horman   IPVS: Add struct ...
286
287
288
  		      ip_vs_proto_name(p->protocol),
  		      IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
  		      IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
28364a59f   Julius Volz   IPVS: Extend func...
289
  		      cp ? "hit" : "not hit");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
292
  
  	return cp;
  }
f11017ec2   Simon Horman   IPVS: Add struct ...
293
  static int
f5099dd4d   Eric W. Biederman   ipvs: Pass ipvs i...
294
295
  ip_vs_conn_fill_param_proto(struct netns_ipvs *ipvs,
  			    int af, const struct sk_buff *skb,
f11017ec2   Simon Horman   IPVS: Add struct ...
296
  			    const struct ip_vs_iphdr *iph,
802c41adc   Alex Gartrell   ipvs: drop invers...
297
  			    struct ip_vs_conn_param *p)
f11017ec2   Simon Horman   IPVS: Add struct ...
298
299
  {
  	__be16 _ports[2], *pptr;
d4383f04d   Jesper Dangaard Brouer   ipvs: API change ...
300
  	pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
f11017ec2   Simon Horman   IPVS: Add struct ...
301
302
  	if (pptr == NULL)
  		return 1;
802c41adc   Alex Gartrell   ipvs: drop invers...
303
  	if (likely(!ip_vs_iph_inverse(iph)))
19913dec1   Eric W. Biederman   ipvs: Pass ipvs n...
304
  		ip_vs_conn_fill_param(ipvs, af, iph->protocol, &iph->saddr,
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
305
  				      pptr[0], &iph->daddr, pptr[1], p);
f11017ec2   Simon Horman   IPVS: Add struct ...
306
  	else
19913dec1   Eric W. Biederman   ipvs: Pass ipvs n...
307
  		ip_vs_conn_fill_param(ipvs, af, iph->protocol, &iph->daddr,
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
308
  				      pptr[1], &iph->saddr, pptr[0], p);
f11017ec2   Simon Horman   IPVS: Add struct ...
309
310
  	return 0;
  }
5c0d2374a   Simon Horman   ipvs: provide def...
311
  struct ip_vs_conn *
ab1619764   Eric W. Biederman   ipvs: Pass ipvs i...
312
313
  ip_vs_conn_in_get_proto(struct netns_ipvs *ipvs, int af,
  			const struct sk_buff *skb,
802c41adc   Alex Gartrell   ipvs: drop invers...
314
  			const struct ip_vs_iphdr *iph)
5c0d2374a   Simon Horman   ipvs: provide def...
315
  {
f11017ec2   Simon Horman   IPVS: Add struct ...
316
  	struct ip_vs_conn_param p;
5c0d2374a   Simon Horman   ipvs: provide def...
317

f5099dd4d   Eric W. Biederman   ipvs: Pass ipvs i...
318
  	if (ip_vs_conn_fill_param_proto(ipvs, af, skb, iph, &p))
5c0d2374a   Simon Horman   ipvs: provide def...
319
  		return NULL;
f11017ec2   Simon Horman   IPVS: Add struct ...
320
  	return ip_vs_conn_in_get(&p);
5c0d2374a   Simon Horman   ipvs: provide def...
321
322
  }
  EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto);
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
323
  /* Get reference to connection template */
f11017ec2   Simon Horman   IPVS: Add struct ...
324
  struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
325
  {
95c961747   Eric Dumazet   net: cleanup unsi...
326
  	unsigned int hash;
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
327
  	struct ip_vs_conn *cp;
85999283a   Simon Horman   IPVS: Add struct ...
328
  	hash = ip_vs_conn_hashkey_param(p, false);
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
329

088339a57   Julian Anastasov   ipvs: convert con...
330
  	rcu_read_lock();
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
331

088339a57   Julian Anastasov   ipvs: convert con...
332
  	hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
1845ed0bb   Julian Anastasov   ipvs: reorder key...
333
  		if (unlikely(p->pe_data && p->pe->ct_match)) {
e64e2b460   Eric W. Biederman   ipvs: Store ipvs ...
334
  			if (cp->ipvs != p->ipvs)
1845ed0bb   Julian Anastasov   ipvs: reorder key...
335
  				continue;
088339a57   Julian Anastasov   ipvs: convert con...
336
337
338
339
  			if (p->pe == cp->pe && p->pe->ct_match(p, cp)) {
  				if (__ip_vs_conn_get(cp))
  					goto out;
  			}
85999283a   Simon Horman   IPVS: Add struct ...
340
341
  			continue;
  		}
f11017ec2   Simon Horman   IPVS: Add struct ...
342
343
  		if (cp->af == p->af &&
  		    ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
be8be9ecc   Simon Horman   ipvs: Fix IPv4 FW...
344
  		    /* protocol should only be IPPROTO_IP if
f11017ec2   Simon Horman   IPVS: Add struct ...
345
346
347
  		     * p->vaddr is a fwmark */
  		    ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC :
  				     p->af, p->vaddr, &cp->vaddr) &&
1845ed0bb   Julian Anastasov   ipvs: reorder key...
348
  		    p->vport == cp->vport && p->cport == cp->cport &&
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
349
  		    cp->flags & IP_VS_CONN_F_TEMPLATE &&
1845ed0bb   Julian Anastasov   ipvs: reorder key...
350
  		    p->protocol == cp->protocol &&
e64e2b460   Eric W. Biederman   ipvs: Store ipvs ...
351
  		    cp->ipvs == p->ipvs) {
088339a57   Julian Anastasov   ipvs: convert con...
352
353
354
  			if (__ip_vs_conn_get(cp))
  				goto out;
  		}
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
355
356
357
358
  	}
  	cp = NULL;
  
    out:
088339a57   Julian Anastasov   ipvs: convert con...
359
  	rcu_read_unlock();
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
360

28364a59f   Julius Volz   IPVS: Extend func...
361
362
  	IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s
  ",
f11017ec2   Simon Horman   IPVS: Add struct ...
363
364
365
  		      ip_vs_proto_name(p->protocol),
  		      IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
  		      IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
28364a59f   Julius Volz   IPVS: Extend func...
366
  		      cp ? "hit" : "not hit");
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
367
368
369
  
  	return cp;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370

f11017ec2   Simon Horman   IPVS: Add struct ...
371
372
373
374
375
  /* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
   * Called for pkts coming from inside-to-OUTside.
   *	p->caddr, p->cport: pkt source address (inside host)
   *	p->vaddr, p->vport: pkt dest address (foreign host) */
  struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  {
95c961747   Eric Dumazet   net: cleanup unsi...
377
  	unsigned int hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
380
381
382
  	struct ip_vs_conn *cp, *ret=NULL;
  
  	/*
  	 *	Check for "full" addressed entries
  	 */
85999283a   Simon Horman   IPVS: Add struct ...
383
  	hash = ip_vs_conn_hashkey_param(p, true);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384

088339a57   Julian Anastasov   ipvs: convert con...
385
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386

088339a57   Julian Anastasov   ipvs: convert con...
387
  	hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
1845ed0bb   Julian Anastasov   ipvs: reorder key...
388
389
  		if (p->vport == cp->cport && p->cport == cp->dport &&
  		    cp->af == p->af &&
f11017ec2   Simon Horman   IPVS: Add struct ...
390
391
  		    ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) &&
  		    ip_vs_addr_equal(p->af, p->caddr, &cp->daddr) &&
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
392
  		    p->protocol == cp->protocol &&
e64e2b460   Eric W. Biederman   ipvs: Store ipvs ...
393
  		    cp->ipvs == p->ipvs) {
088339a57   Julian Anastasov   ipvs: convert con...
394
395
  			if (!__ip_vs_conn_get(cp))
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  			/* HIT */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
  			ret = cp;
  			break;
  		}
  	}
088339a57   Julian Anastasov   ipvs: convert con...
401
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402

28364a59f   Julius Volz   IPVS: Extend func...
403
404
  	IP_VS_DBG_BUF(9, "lookup/out %s %s:%d->%s:%d %s
  ",
f11017ec2   Simon Horman   IPVS: Add struct ...
405
406
407
  		      ip_vs_proto_name(p->protocol),
  		      IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
  		      IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
28364a59f   Julius Volz   IPVS: Extend func...
408
  		      ret ? "hit" : "not hit");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
  
  	return ret;
  }
5c0d2374a   Simon Horman   ipvs: provide def...
412
  struct ip_vs_conn *
0cf705c8c   Eric W. Biederman   ipvs: Pass ipvs i...
413
414
  ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af,
  			 const struct sk_buff *skb,
802c41adc   Alex Gartrell   ipvs: drop invers...
415
  			 const struct ip_vs_iphdr *iph)
5c0d2374a   Simon Horman   ipvs: provide def...
416
  {
f11017ec2   Simon Horman   IPVS: Add struct ...
417
  	struct ip_vs_conn_param p;
5c0d2374a   Simon Horman   ipvs: provide def...
418

f5099dd4d   Eric W. Biederman   ipvs: Pass ipvs i...
419
  	if (ip_vs_conn_fill_param_proto(ipvs, af, skb, iph, &p))
5c0d2374a   Simon Horman   ipvs: provide def...
420
  		return NULL;
f11017ec2   Simon Horman   IPVS: Add struct ...
421
  	return ip_vs_conn_out_get(&p);
5c0d2374a   Simon Horman   ipvs: provide def...
422
423
  }
  EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424

013b04246   Marco Angaroni   ipvs: optimize re...
425
426
427
428
429
  static void __ip_vs_conn_put_notimer(struct ip_vs_conn *cp)
  {
  	__ip_vs_conn_put(cp);
  	ip_vs_conn_expire((unsigned long)cp);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
  /*
   *      Put back the conn and restart its timer with its timeout
   */
013b04246   Marco Angaroni   ipvs: optimize re...
433
  static void __ip_vs_conn_put_timer(struct ip_vs_conn *cp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  {
26ec037f9   Nick Chalk   IPVS: one-packet ...
435
436
437
  	unsigned long t = (cp->flags & IP_VS_CONN_F_ONE_PACKET) ?
  		0 : cp->timeout;
  	mod_timer(&cp->timer, jiffies+t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
440
  
  	__ip_vs_conn_put(cp);
  }
013b04246   Marco Angaroni   ipvs: optimize re...
441
442
443
444
445
446
447
448
449
450
  void ip_vs_conn_put(struct ip_vs_conn *cp)
  {
  	if ((cp->flags & IP_VS_CONN_F_ONE_PACKET) &&
  	    (atomic_read(&cp->refcnt) == 1) &&
  	    !timer_pending(&cp->timer))
  		/* expire connection immediately */
  		__ip_vs_conn_put_notimer(cp);
  	else
  		__ip_vs_conn_put_timer(cp);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
  
  /*
   *	Fill a no_client_port connection with a client port number
   */
014d730d5   Al Viro   [IPVS]: ipvs anno...
455
  void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
  {
  	if (ip_vs_conn_unhash(cp)) {
ac69269a4   Julian Anastasov   ipvs: do not disa...
458
  		spin_lock_bh(&cp->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
462
463
  		if (cp->flags & IP_VS_CONN_F_NO_CPORT) {
  			atomic_dec(&ip_vs_conn_no_cport_cnt);
  			cp->flags &= ~IP_VS_CONN_F_NO_CPORT;
  			cp->cport = cport;
  		}
ac69269a4   Julian Anastasov   ipvs: do not disa...
464
  		spin_unlock_bh(&cp->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
  
  		/* hash on new dport */
  		ip_vs_conn_hash(cp);
  	}
  }
  
  
  /*
   *	Bind a connection entry with the corresponding packet_xmit.
   *	Called by ip_vs_conn_new.
   */
  static inline void ip_vs_bind_xmit(struct ip_vs_conn *cp)
  {
  	switch (IP_VS_FWD_METHOD(cp)) {
  	case IP_VS_CONN_F_MASQ:
  		cp->packet_xmit = ip_vs_nat_xmit;
  		break;
  
  	case IP_VS_CONN_F_TUNNEL:
8052ba292   Alex Gartrell   ipvs: support ipv...
484
485
486
487
488
489
  #ifdef CONFIG_IP_VS_IPV6
  		if (cp->daf == AF_INET6)
  			cp->packet_xmit = ip_vs_tunnel_xmit_v6;
  		else
  #endif
  			cp->packet_xmit = ip_vs_tunnel_xmit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  		break;
  
  	case IP_VS_CONN_F_DROUTE:
  		cp->packet_xmit = ip_vs_dr_xmit;
  		break;
  
  	case IP_VS_CONN_F_LOCALNODE:
  		cp->packet_xmit = ip_vs_null_xmit;
  		break;
  
  	case IP_VS_CONN_F_BYPASS:
  		cp->packet_xmit = ip_vs_bypass_xmit;
  		break;
  	}
  }
b3cdd2a73   Julius Volz   IPVS: Add and bin...
505
506
507
508
509
510
511
512
513
  #ifdef CONFIG_IP_VS_IPV6
  static inline void ip_vs_bind_xmit_v6(struct ip_vs_conn *cp)
  {
  	switch (IP_VS_FWD_METHOD(cp)) {
  	case IP_VS_CONN_F_MASQ:
  		cp->packet_xmit = ip_vs_nat_xmit_v6;
  		break;
  
  	case IP_VS_CONN_F_TUNNEL:
8052ba292   Alex Gartrell   ipvs: support ipv...
514
515
516
517
  		if (cp->daf == AF_INET6)
  			cp->packet_xmit = ip_vs_tunnel_xmit_v6;
  		else
  			cp->packet_xmit = ip_vs_tunnel_xmit;
b3cdd2a73   Julius Volz   IPVS: Add and bin...
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  		break;
  
  	case IP_VS_CONN_F_DROUTE:
  		cp->packet_xmit = ip_vs_dr_xmit_v6;
  		break;
  
  	case IP_VS_CONN_F_LOCALNODE:
  		cp->packet_xmit = ip_vs_null_xmit;
  		break;
  
  	case IP_VS_CONN_F_BYPASS:
  		cp->packet_xmit = ip_vs_bypass_xmit_v6;
  		break;
  	}
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
539
540
541
542
543
544
545
546
547
  
  static inline int ip_vs_dest_totalconns(struct ip_vs_dest *dest)
  {
  	return atomic_read(&dest->activeconns)
  		+ atomic_read(&dest->inactconns);
  }
  
  /*
   *	Bind a connection entry with a virtual service destination
   *	Called just after a new connection entry is created.
   */
  static inline void
  ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
  {
3575792e0   Julian Anastasov   ipvs: extend conn...
548
  	unsigned int conn_flags;
6b324dbfc   Pablo Neira Ayuso   ipvs: optimize th...
549
  	__u32 flags;
3575792e0   Julian Anastasov   ipvs: extend conn...
550

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
555
  	/* if dest is NULL, then return directly */
  	if (!dest)
  		return;
  
  	/* Increase the refcnt counter of the dest */
fca9c20ae   Julian Anastasov   ipvs: add ip_vs_d...
556
  	ip_vs_dest_hold(dest);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557

3575792e0   Julian Anastasov   ipvs: extend conn...
558
559
560
  	conn_flags = atomic_read(&dest->conn_flags);
  	if (cp->protocol != IPPROTO_UDP)
  		conn_flags &= ~IP_VS_CONN_F_ONE_PACKET;
6b324dbfc   Pablo Neira Ayuso   ipvs: optimize th...
561
  	flags = cp->flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  	/* Bind with the destination and its corresponding transmitter */
6b324dbfc   Pablo Neira Ayuso   ipvs: optimize th...
563
  	if (flags & IP_VS_CONN_F_SYNC) {
b209639e8   Rumen G. Bogdanovski   [IPVS]: Create sy...
564
565
566
  		/* if the connection is not template and is created
  		 * by sync, preserve the activity flag.
  		 */
6b324dbfc   Pablo Neira Ayuso   ipvs: optimize th...
567
  		if (!(flags & IP_VS_CONN_F_TEMPLATE))
3575792e0   Julian Anastasov   ipvs: extend conn...
568
  			conn_flags &= ~IP_VS_CONN_F_INACTIVE;
3233759be   Julian Anastasov   ipvs: inherit for...
569
  		/* connections inherit forwarding method from dest */
6b324dbfc   Pablo Neira Ayuso   ipvs: optimize th...
570
  		flags &= ~(IP_VS_CONN_F_FWD_MASK | IP_VS_CONN_F_NOOUTPUT);
3575792e0   Julian Anastasov   ipvs: extend conn...
571
  	}
6b324dbfc   Pablo Neira Ayuso   ipvs: optimize th...
572
573
  	flags |= conn_flags;
  	cp->flags = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  	cp->dest = dest;
cfc78c5a0   Julius Volz   IPVS: Adjust vari...
575
576
577
578
579
580
581
  	IP_VS_DBG_BUF(7, "Bind-dest %s c:%s:%d v:%s:%d "
  		      "d:%s:%d fwd:%c s:%u conn->flags:%X conn->refcnt:%d "
  		      "dest->refcnt:%d
  ",
  		      ip_vs_proto_name(cp->protocol),
  		      IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
  		      IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
f18ae7206   Julian Anastasov   ipvs: use the new...
582
  		      IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
cfc78c5a0   Julius Volz   IPVS: Adjust vari...
583
584
585
  		      ip_vs_fwd_tag(cp), cp->state,
  		      cp->flags, atomic_read(&cp->refcnt),
  		      atomic_read(&dest->refcnt));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
  
  	/* Update the connection counters */
6b324dbfc   Pablo Neira Ayuso   ipvs: optimize th...
588
  	if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
06611f82c   Julian Anastasov   ipvs: remove chec...
589
590
591
592
  		/* It is a normal connection, so modify the counters
  		 * according to the flags, later the protocol can
  		 * update them on state change
  		 */
6b324dbfc   Pablo Neira Ayuso   ipvs: optimize th...
593
  		if (!(flags & IP_VS_CONN_F_INACTIVE))
b209639e8   Rumen G. Bogdanovski   [IPVS]: Create sy...
594
595
596
  			atomic_inc(&dest->activeconns);
  		else
  			atomic_inc(&dest->inactconns);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
  	} else {
  		/* It is a persistent connection/template, so increase
25985edce   Lucas De Marchi   Fix common misspe...
599
  		   the persistent connection counter */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
602
603
604
605
606
607
608
609
  		atomic_inc(&dest->persistconns);
  	}
  
  	if (dest->u_threshold != 0 &&
  	    ip_vs_dest_totalconns(dest) >= dest->u_threshold)
  		dest->flags |= IP_VS_DEST_F_OVERLOAD;
  }
  
  
  /*
1e356f9cd   Rumen G. Bogdanovski   [IPVS]: Bind conn...
610
611
612
   * Check if there is a destination for the connection, if so
   * bind the connection to the destination.
   */
413c2d04e   Julian Anastasov   ipvs: convert des...
613
  void ip_vs_try_bind_dest(struct ip_vs_conn *cp)
1e356f9cd   Rumen G. Bogdanovski   [IPVS]: Bind conn...
614
615
  {
  	struct ip_vs_dest *dest;
413c2d04e   Julian Anastasov   ipvs: convert des...
616
  	rcu_read_lock();
655eef103   Alex Gartrell   ipvs: Supply dest...
617
618
619
620
621
622
  
  	/* This function is only invoked by the synchronization code. We do
  	 * not currently support heterogeneous pools with synchronization,
  	 * so we can make the assumption that the svc_af is the same as the
  	 * dest_af
  	 */
dc2add6f2   Eric W. Biederman   ipvs: Pass ipvs n...
623
  	dest = ip_vs_find_dest(cp->ipvs, cp->af, cp->af, &cp->daddr,
882a844bd   Julian Anastasov   ipvs: fix ip_vs_t...
624
625
626
627
  			       cp->dport, &cp->vaddr, cp->vport,
  			       cp->protocol, cp->fwmark, cp->flags);
  	if (dest) {
  		struct ip_vs_proto_data *pd;
ac69269a4   Julian Anastasov   ipvs: do not disa...
628
  		spin_lock_bh(&cp->lock);
f73181c82   Pablo Neira Ayuso   ipvs: add support...
629
  		if (cp->dest) {
ac69269a4   Julian Anastasov   ipvs: do not disa...
630
  			spin_unlock_bh(&cp->lock);
413c2d04e   Julian Anastasov   ipvs: convert des...
631
632
  			rcu_read_unlock();
  			return;
f73181c82   Pablo Neira Ayuso   ipvs: add support...
633
  		}
882a844bd   Julian Anastasov   ipvs: fix ip_vs_t...
634
635
636
637
  		/* Applications work depending on the forwarding method
  		 * but better to reassign them always when binding dest */
  		if (cp->app)
  			ip_vs_unbind_app(cp);
1e356f9cd   Rumen G. Bogdanovski   [IPVS]: Bind conn...
638
  		ip_vs_bind_dest(cp, dest);
ac69269a4   Julian Anastasov   ipvs: do not disa...
639
  		spin_unlock_bh(&cp->lock);
882a844bd   Julian Anastasov   ipvs: fix ip_vs_t...
640
641
642
643
644
645
646
647
648
  
  		/* Update its packet transmitter */
  		cp->packet_xmit = NULL;
  #ifdef CONFIG_IP_VS_IPV6
  		if (cp->af == AF_INET6)
  			ip_vs_bind_xmit_v6(cp);
  		else
  #endif
  			ip_vs_bind_xmit(cp);
18d6ade63   Eric W. Biederman   ipvs: Pass ipvs n...
649
  		pd = ip_vs_proto_data_get(cp->ipvs, cp->protocol);
882a844bd   Julian Anastasov   ipvs: fix ip_vs_t...
650
651
652
  		if (pd && atomic_read(&pd->appcnt))
  			ip_vs_bind_app(cp, pd->pp);
  	}
413c2d04e   Julian Anastasov   ipvs: convert des...
653
  	rcu_read_unlock();
1e356f9cd   Rumen G. Bogdanovski   [IPVS]: Bind conn...
654
  }
1e356f9cd   Rumen G. Bogdanovski   [IPVS]: Bind conn...
655
656
657
  
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
662
663
664
665
666
   *	Unbind a connection entry with its VS destination
   *	Called by the ip_vs_conn_expire function.
   */
  static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
  {
  	struct ip_vs_dest *dest = cp->dest;
  
  	if (!dest)
  		return;
cfc78c5a0   Julius Volz   IPVS: Adjust vari...
667
668
669
670
671
672
673
  	IP_VS_DBG_BUF(7, "Unbind-dest %s c:%s:%d v:%s:%d "
  		      "d:%s:%d fwd:%c s:%u conn->flags:%X conn->refcnt:%d "
  		      "dest->refcnt:%d
  ",
  		      ip_vs_proto_name(cp->protocol),
  		      IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
  		      IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
f18ae7206   Julian Anastasov   ipvs: use the new...
674
  		      IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
cfc78c5a0   Julius Volz   IPVS: Adjust vari...
675
676
677
  		      ip_vs_fwd_tag(cp), cp->state,
  		      cp->flags, atomic_read(&cp->refcnt),
  		      atomic_read(&dest->refcnt));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
  
  	/* Update the connection counters */
87375ab47   Julian Anastasov   [IPVS]: ip_vs_ftp...
680
  	if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
683
684
685
686
687
688
689
  		/* It is a normal connection, so decrease the inactconns
  		   or activeconns counter */
  		if (cp->flags & IP_VS_CONN_F_INACTIVE) {
  			atomic_dec(&dest->inactconns);
  		} else {
  			atomic_dec(&dest->activeconns);
  		}
  	} else {
  		/* It is a persistent connection/template, so decrease
25985edce   Lucas De Marchi   Fix common misspe...
690
  		   the persistent connection counter */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
693
694
695
696
697
698
699
700
701
702
703
  		atomic_dec(&dest->persistconns);
  	}
  
  	if (dest->l_threshold != 0) {
  		if (ip_vs_dest_totalconns(dest) < dest->l_threshold)
  			dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
  	} else if (dest->u_threshold != 0) {
  		if (ip_vs_dest_totalconns(dest) * 4 < dest->u_threshold * 3)
  			dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
  	} else {
  		if (dest->flags & IP_VS_DEST_F_OVERLOAD)
  			dest->flags &= ~IP_VS_DEST_F_OVERLOAD;
  	}
fca9c20ae   Julian Anastasov   ipvs: add ip_vs_d...
704
  	ip_vs_dest_put(dest);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
  }
8e1b0b1b5   Simon Horman   IPVS: Add expire_...
706
707
708
709
710
711
712
713
714
715
  static int expire_quiescent_template(struct netns_ipvs *ipvs,
  				     struct ip_vs_dest *dest)
  {
  #ifdef CONFIG_SYSCTL
  	return ipvs->sysctl_expire_quiescent_template &&
  		(atomic_read(&dest->weight) == 0);
  #else
  	return 0;
  #endif
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
717
718
719
720
721
  
  /*
   *	Checking if the destination of a connection template is available.
   *	If available, return 1, otherwise invalidate this connection
   *	template and return 0.
   */
3ec10d3a2   Marco Angaroni   ipvs: update real...
722
  int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
  {
  	struct ip_vs_dest *dest = ct->dest;
58dbc6f26   Eric W. Biederman   ipvs: Store ipvs ...
725
  	struct netns_ipvs *ipvs = ct->ipvs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
728
729
730
  
  	/*
  	 * Checking the dest server status.
  	 */
  	if ((dest == NULL) ||
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
731
  	    !(dest->flags & IP_VS_DEST_F_AVAILABLE) ||
3ec10d3a2   Marco Angaroni   ipvs: update real...
732
733
  	    expire_quiescent_template(ipvs, dest) ||
  	    (cdest && (dest != cdest))) {
cfc78c5a0   Julius Volz   IPVS: Adjust vari...
734
735
736
737
738
739
740
741
742
  		IP_VS_DBG_BUF(9, "check_template: dest not available for "
  			      "protocol %s s:%s:%d v:%s:%d "
  			      "-> d:%s:%d
  ",
  			      ip_vs_proto_name(ct->protocol),
  			      IP_VS_DBG_ADDR(ct->af, &ct->caddr),
  			      ntohs(ct->cport),
  			      IP_VS_DBG_ADDR(ct->af, &ct->vaddr),
  			      ntohs(ct->vport),
f18ae7206   Julian Anastasov   ipvs: use the new...
743
  			      IP_VS_DBG_ADDR(ct->daf, &ct->daddr),
cfc78c5a0   Julius Volz   IPVS: Adjust vari...
744
  			      ntohs(ct->dport));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
746
747
748
  
  		/*
  		 * Invalidate the connection template
  		 */
014d730d5   Al Viro   [IPVS]: ipvs anno...
749
  		if (ct->vport != htons(0xffff)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  			if (ip_vs_conn_unhash(ct)) {
014d730d5   Al Viro   [IPVS]: ipvs anno...
751
752
  				ct->dport = htons(0xffff);
  				ct->vport = htons(0xffff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
754
755
756
757
758
759
760
761
  				ct->cport = 0;
  				ip_vs_conn_hash(ct);
  			}
  		}
  
  		/*
  		 * Simply decrease the refcnt of the template,
  		 * don't restart its timer.
  		 */
088339a57   Julian Anastasov   ipvs: convert con...
762
  		__ip_vs_conn_put(ct);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763
764
765
766
  		return 0;
  	}
  	return 1;
  }
088339a57   Julian Anastasov   ipvs: convert con...
767
768
769
770
771
772
773
774
775
  static void ip_vs_conn_rcu_free(struct rcu_head *head)
  {
  	struct ip_vs_conn *cp = container_of(head, struct ip_vs_conn,
  					     rcu_head);
  
  	ip_vs_pe_put(cp->pe);
  	kfree(cp->pe_data);
  	kmem_cache_free(ip_vs_conn_cachep, cp);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
777
778
  static void ip_vs_conn_expire(unsigned long data)
  {
  	struct ip_vs_conn *cp = (struct ip_vs_conn *)data;
58dbc6f26   Eric W. Biederman   ipvs: Store ipvs ...
779
  	struct netns_ipvs *ipvs = cp->ipvs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
783
784
785
  	/*
  	 *	do I control anybody?
  	 */
  	if (atomic_read(&cp->n_control))
  		goto expire_later;
088339a57   Julian Anastasov   ipvs: convert con...
786
787
  	/* Unlink conn if not referenced anymore */
  	if (likely(ip_vs_conn_unlink(cp))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
  		/* delete the timer if it is activated by other users */
25cc4ae91   Ying Xue   net: remove redun...
789
  		del_timer(&cp->timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
791
792
793
  
  		/* does anybody control me? */
  		if (cp->control)
  			ip_vs_control_del(cp);
8fb04d9fc   Marco Angaroni   ipvs: don't alter...
794
795
  		if ((cp->flags & IP_VS_CONN_F_NFCT) &&
  		    !(cp->flags & IP_VS_CONN_F_ONE_PACKET)) {
8f4e0a186   Hans Schillstrom   IPVS netns exit c...
796
797
798
799
800
801
802
803
  			/* Do not access conntracks during subsys cleanup
  			 * because nf_conntrack_find_get can not be used after
  			 * conntrack cleanup for the net.
  			 */
  			smp_rmb();
  			if (ipvs->enable)
  				ip_vs_conn_drop_conntrack(cp);
  		}
f4bc17cdd   Julian Anastasov   ipvs: netfilter c...
804

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
806
807
808
809
  		if (unlikely(cp->app != NULL))
  			ip_vs_unbind_app(cp);
  		ip_vs_unbind_dest(cp);
  		if (cp->flags & IP_VS_CONN_F_NO_CPORT)
  			atomic_dec(&ip_vs_conn_no_cport_cnt);
013b04246   Marco Angaroni   ipvs: optimize re...
810
811
812
813
  		if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
  			ip_vs_conn_rcu_free(&cp->rcu_head);
  		else
  			call_rcu(&cp->rcu_head, ip_vs_conn_rcu_free);
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
814
  		atomic_dec(&ipvs->conn_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
816
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
    expire_later:
088339a57   Julian Anastasov   ipvs: convert con...
818
819
820
  	IP_VS_DBG(7, "delayed: conn->refcnt=%d conn->n_control=%d
  ",
  		  atomic_read(&cp->refcnt),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
  		  atomic_read(&cp->n_control));
088339a57   Julian Anastasov   ipvs: convert con...
822
823
  	atomic_inc(&cp->refcnt);
  	cp->timeout = 60*HZ;
749c42b62   Julian Anastasov   ipvs: reduce sync...
824
  	if (ipvs->sync_state & IP_VS_STATE_MASTER)
b61a8c1a4   Eric W. Biederman   ipvs: Pass ipvs n...
825
  		ip_vs_sync_conn(ipvs, cp, sysctl_sync_threshold(ipvs));
749c42b62   Julian Anastasov   ipvs: reduce sync...
826

013b04246   Marco Angaroni   ipvs: optimize re...
827
  	__ip_vs_conn_put_timer(cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
  }
088339a57   Julian Anastasov   ipvs: convert con...
829
830
831
  /* Modify timer, so that it expires as soon as possible.
   * Can be called without reference only if under RCU lock.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
833
  void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
  {
088339a57   Julian Anastasov   ipvs: convert con...
834
835
836
837
838
839
  	/* Using mod_timer_pending will ensure the timer is not
  	 * modified after the final del_timer in ip_vs_conn_expire.
  	 */
  	if (timer_pending(&cp->timer) &&
  	    time_after(cp->timer.expires, jiffies))
  		mod_timer_pending(&cp->timer, jiffies);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
841
842
843
844
845
846
  }
  
  
  /*
   *	Create a new connection entry and hash it into the ip_vs_conn_tab
   */
  struct ip_vs_conn *
ba38528aa   Alex Gartrell   ipvs: Supply dest...
847
  ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
95c961747   Eric Dumazet   net: cleanup unsi...
848
  	       const union nf_inet_addr *daddr, __be16 dport, unsigned int flags,
0e051e683   Hans Schillstrom   IPVS: Backup, Pre...
849
  	       struct ip_vs_dest *dest, __u32 fwmark)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850
851
  {
  	struct ip_vs_conn *cp;
e64e2b460   Eric W. Biederman   ipvs: Store ipvs ...
852
  	struct netns_ipvs *ipvs = p->ipvs;
18d6ade63   Eric W. Biederman   ipvs: Pass ipvs n...
853
  	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(p->ipvs,
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
854
  							   p->protocol);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855

9a05475ce   Julian Anastasov   ipvs: avoid kmem_...
856
  	cp = kmem_cache_alloc(ip_vs_conn_cachep, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
  	if (cp == NULL) {
1e3e238e9   Hannes Eder   IPVS: use pr_err ...
858
859
  		IP_VS_ERR_RL("%s(): no memory
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
  		return NULL;
  	}
731109e78   Changli Gao   ipvs: use hlist i...
862
  	INIT_HLIST_NODE(&cp->c_list);
b24b8a247   Pavel Emelyanov   [NET]: Convert in...
863
  	setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
58dbc6f26   Eric W. Biederman   ipvs: Store ipvs ...
864
  	cp->ipvs	   = ipvs;
f11017ec2   Simon Horman   IPVS: Add struct ...
865
  	cp->af		   = p->af;
ba38528aa   Alex Gartrell   ipvs: Supply dest...
866
  	cp->daf		   = dest_af;
f11017ec2   Simon Horman   IPVS: Add struct ...
867
  	cp->protocol	   = p->protocol;
9a05475ce   Julian Anastasov   ipvs: avoid kmem_...
868
  	ip_vs_addr_set(p->af, &cp->caddr, p->caddr);
f11017ec2   Simon Horman   IPVS: Add struct ...
869
  	cp->cport	   = p->cport;
2a971354e   Michal Kubecek   ipvs: fix AF assi...
870
  	/* proto should only be IPPROTO_IP if p->vaddr is a fwmark */
9a05475ce   Julian Anastasov   ipvs: avoid kmem_...
871
  	ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
2a971354e   Michal Kubecek   ipvs: fix AF assi...
872
873
  		       &cp->vaddr, p->vaddr);
  	cp->vport	   = p->vport;
ba38528aa   Alex Gartrell   ipvs: Supply dest...
874
  	ip_vs_addr_set(cp->daf, &cp->daddr, daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
876
  	cp->dport          = dport;
  	cp->flags	   = flags;
0e051e683   Hans Schillstrom   IPVS: Backup, Pre...
877
  	cp->fwmark         = fwmark;
e9e5eee87   Simon Horman   IPVS: Add persist...
878
879
880
  	if (flags & IP_VS_CONN_F_TEMPLATE && p->pe) {
  		ip_vs_pe_get(p->pe);
  		cp->pe = p->pe;
85999283a   Simon Horman   IPVS: Add struct ...
881
882
  		cp->pe_data = p->pe_data;
  		cp->pe_data_len = p->pe_data_len;
9a05475ce   Julian Anastasov   ipvs: avoid kmem_...
883
884
885
886
  	} else {
  		cp->pe = NULL;
  		cp->pe_data = NULL;
  		cp->pe_data_len = 0;
85999283a   Simon Horman   IPVS: Add struct ...
887
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
889
890
891
892
893
894
895
  	spin_lock_init(&cp->lock);
  
  	/*
  	 * Set the entry is referenced by the current thread before hashing
  	 * it in the table, so that other thread run ip_vs_random_dropentry
  	 * but cannot drop this entry.
  	 */
  	atomic_set(&cp->refcnt, 1);
9a05475ce   Julian Anastasov   ipvs: avoid kmem_...
896
  	cp->control = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
  	atomic_set(&cp->n_control, 0);
  	atomic_set(&cp->in_pkts, 0);
9a05475ce   Julian Anastasov   ipvs: avoid kmem_...
899
900
901
902
903
904
  	cp->packet_xmit = NULL;
  	cp->app = NULL;
  	cp->app_data = NULL;
  	/* reset struct ip_vs_seq */
  	cp->in_seq.delta = 0;
  	cp->out_seq.delta = 0;
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
905
  	atomic_inc(&ipvs->conn_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
907
908
909
  	if (flags & IP_VS_CONN_F_NO_CPORT)
  		atomic_inc(&ip_vs_conn_no_cport_cnt);
  
  	/* Bind the connection with a destination server */
9a05475ce   Julian Anastasov   ipvs: avoid kmem_...
910
  	cp->dest = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
913
914
  	ip_vs_bind_dest(cp, dest);
  
  	/* Set its state and timeout */
  	cp->state = 0;
9a05475ce   Julian Anastasov   ipvs: avoid kmem_...
915
  	cp->old_state = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
  	cp->timeout = 3*HZ;
749c42b62   Julian Anastasov   ipvs: reduce sync...
917
  	cp->sync_endtime = jiffies & ~3UL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
  
  	/* Bind its packet transmitter */
b3cdd2a73   Julius Volz   IPVS: Add and bin...
920
  #ifdef CONFIG_IP_VS_IPV6
f11017ec2   Simon Horman   IPVS: Add struct ...
921
  	if (p->af == AF_INET6)
b3cdd2a73   Julius Volz   IPVS: Add and bin...
922
923
924
925
  		ip_vs_bind_xmit_v6(cp);
  	else
  #endif
  		ip_vs_bind_xmit(cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926

9bbac6a90   Hans Schillstrom   IPVS: netns, comm...
927
928
  	if (unlikely(pd && atomic_read(&pd->appcnt)))
  		ip_vs_bind_app(cp, pd->pp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929

f4bc17cdd   Julian Anastasov   ipvs: netfilter c...
930
931
932
933
934
935
  	/*
  	 * Allow conntrack to be preserved. By default, conntrack
  	 * is created and destroyed for every packet.
  	 * Sometimes keeping conntrack can be useful for
  	 * IP_VS_CONN_F_ONE_PACKET too.
  	 */
a0840e2e1   Hans Schillstrom   IPVS: netns, ip_v...
936
  	if (ip_vs_conntrack_enabled(ipvs))
f4bc17cdd   Julian Anastasov   ipvs: netfilter c...
937
  		cp->flags |= IP_VS_CONN_F_NFCT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
941
942
  	/* Hash it in the ip_vs_conn_tab finally */
  	ip_vs_conn_hash(cp);
  
  	return cp;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
943
944
945
946
  /*
   *	/proc/net/ip_vs_conn entries
   */
  #ifdef CONFIG_PROC_FS
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
947
  struct ip_vs_iter_state {
731109e78   Changli Gao   ipvs: use hlist i...
948
949
  	struct seq_net_private	p;
  	struct hlist_head	*l;
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
950
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
951
952
953
954
955
  
  static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
  {
  	int idx;
  	struct ip_vs_conn *cp;
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
956
  	struct ip_vs_iter_state *iter = seq->private;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
957

6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
958
  	for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
088339a57   Julian Anastasov   ipvs: convert con...
959
960
961
962
  		hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
  			/* __ip_vs_conn_get() is not needed by
  			 * ip_vs_conn_seq_show and ip_vs_conn_sync_seq_show
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
  			if (pos-- == 0) {
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
964
  				iter->l = &ip_vs_conn_tab[idx];
731109e78   Changli Gao   ipvs: use hlist i...
965
  				return cp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
  			}
  		}
a38e5e230   Simon Horman   ipvs: use cond_re...
968
  		cond_resched_rcu();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
969
970
971
972
973
974
  	}
  
  	return NULL;
  }
  
  static void *ip_vs_conn_seq_start(struct seq_file *seq, loff_t *pos)
7cf2eb7bc   Julian Anastasov   ipvs: fix sparse ...
975
  	__acquires(RCU)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976
  {
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
977
978
979
  	struct ip_vs_iter_state *iter = seq->private;
  
  	iter->l = NULL;
7cf2eb7bc   Julian Anastasov   ipvs: fix sparse ...
980
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
982
983
984
985
986
  	return *pos ? ip_vs_conn_array(seq, *pos - 1) :SEQ_START_TOKEN;
  }
  
  static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
  	struct ip_vs_conn *cp = v;
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
987
  	struct ip_vs_iter_state *iter = seq->private;
088339a57   Julian Anastasov   ipvs: convert con...
988
  	struct hlist_node *e;
731109e78   Changli Gao   ipvs: use hlist i...
989
  	struct hlist_head *l = iter->l;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
991
992
  	int idx;
  
  	++*pos;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
993
  	if (v == SEQ_START_TOKEN)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
995
996
  		return ip_vs_conn_array(seq, 0);
  
  	/* more on same hash chain? */
088339a57   Julian Anastasov   ipvs: convert con...
997
998
999
  	e = rcu_dereference(hlist_next_rcu(&cp->c_list));
  	if (e)
  		return hlist_entry(e, struct ip_vs_conn, c_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000
1001
  
  	idx = l - ip_vs_conn_tab;
6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
1002
  	while (++idx < ip_vs_conn_tab_size) {
088339a57   Julian Anastasov   ipvs: convert con...
1003
  		hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1004
  			iter->l = &ip_vs_conn_tab[idx];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1005
  			return cp;
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1006
  		}
a38e5e230   Simon Horman   ipvs: use cond_re...
1007
  		cond_resched_rcu();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
  	}
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1009
  	iter->l = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010
1011
1012
1013
  	return NULL;
  }
  
  static void ip_vs_conn_seq_stop(struct seq_file *seq, void *v)
7cf2eb7bc   Julian Anastasov   ipvs: fix sparse ...
1014
  	__releases(RCU)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
  {
7cf2eb7bc   Julian Anastasov   ipvs: fix sparse ...
1016
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1017
1018
1019
1020
1021
1022
1023
  }
  
  static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
  {
  
  	if (v == SEQ_START_TOKEN)
  		seq_puts(seq,
a3c918acd   Simon Horman   IPVS: Add persist...
1024
1025
     "Pro FromIP   FPrt ToIP     TPrt DestIP   DPrt State       Expires PEName PEData
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
1027
  	else {
  		const struct ip_vs_conn *cp = v;
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1028
  		struct net *net = seq_file_net(seq);
a3c918acd   Simon Horman   IPVS: Add persist...
1029
1030
  		char pe_data[IP_VS_PENAME_MAXLEN + IP_VS_PEDATA_MAXLEN + 3];
  		size_t len = 0;
f18ae7206   Julian Anastasov   ipvs: use the new...
1031
  		char dbuf[IP_VS_ADDRSTRLEN];
a3c918acd   Simon Horman   IPVS: Add persist...
1032

58dbc6f26   Eric W. Biederman   ipvs: Store ipvs ...
1033
  		if (!net_eq(cp->ipvs->net, net))
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1034
  			return 0;
e9e5eee87   Simon Horman   IPVS: Add persist...
1035
  		if (cp->pe_data) {
a3c918acd   Simon Horman   IPVS: Add persist...
1036
  			pe_data[0] = ' ';
e9e5eee87   Simon Horman   IPVS: Add persist...
1037
1038
  			len = strlen(cp->pe->name);
  			memcpy(pe_data + 1, cp->pe->name, len);
a3c918acd   Simon Horman   IPVS: Add persist...
1039
1040
  			pe_data[len + 1] = ' ';
  			len += 2;
e9e5eee87   Simon Horman   IPVS: Add persist...
1041
  			len += cp->pe->show_pe_data(cp, pe_data + len);
a3c918acd   Simon Horman   IPVS: Add persist...
1042
1043
  		}
  		pe_data[len] = '\0';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1044

667a5f181   Vince Busam   IPVS: Convert pro...
1045
  #ifdef CONFIG_IP_VS_IPV6
f18ae7206   Julian Anastasov   ipvs: use the new...
1046
1047
1048
1049
1050
1051
1052
1053
  		if (cp->daf == AF_INET6)
  			snprintf(dbuf, sizeof(dbuf), "%pI6", &cp->daddr.in6);
  		else
  #endif
  			snprintf(dbuf, sizeof(dbuf), "%08X",
  				 ntohl(cp->daddr.ip));
  
  #ifdef CONFIG_IP_VS_IPV6
667a5f181   Vince Busam   IPVS: Convert pro...
1054
  		if (cp->af == AF_INET6)
a3c918acd   Simon Horman   IPVS: Add persist...
1055
  			seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X "
f18ae7206   Julian Anastasov   ipvs: use the new...
1056
1057
  				"%s %04X %-11s %7lu%s
  ",
667a5f181   Vince Busam   IPVS: Convert pro...
1058
  				ip_vs_proto_name(cp->protocol),
38ff4fa49   Harvey Harrison   netfilter: replac...
1059
1060
  				&cp->caddr.in6, ntohs(cp->cport),
  				&cp->vaddr.in6, ntohs(cp->vport),
f18ae7206   Julian Anastasov   ipvs: use the new...
1061
  				dbuf, ntohs(cp->dport),
667a5f181   Vince Busam   IPVS: Convert pro...
1062
  				ip_vs_state_name(cp->protocol, cp->state),
a3c918acd   Simon Horman   IPVS: Add persist...
1063
  				(cp->timer.expires-jiffies)/HZ, pe_data);
667a5f181   Vince Busam   IPVS: Convert pro...
1064
1065
1066
1067
  		else
  #endif
  			seq_printf(seq,
  				"%-3s %08X %04X %08X %04X"
f18ae7206   Julian Anastasov   ipvs: use the new...
1068
1069
  				" %s %04X %-11s %7lu%s
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
  				ip_vs_proto_name(cp->protocol),
e7ade46a5   Julius Volz   IPVS: Change IPVS...
1071
1072
  				ntohl(cp->caddr.ip), ntohs(cp->cport),
  				ntohl(cp->vaddr.ip), ntohs(cp->vport),
f18ae7206   Julian Anastasov   ipvs: use the new...
1073
  				dbuf, ntohs(cp->dport),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
  				ip_vs_state_name(cp->protocol, cp->state),
a3c918acd   Simon Horman   IPVS: Add persist...
1075
  				(cp->timer.expires-jiffies)/HZ, pe_data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
  	}
  	return 0;
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
1079
  static const struct seq_operations ip_vs_conn_seq_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1080
1081
1082
1083
1084
1085
1086
1087
  	.start = ip_vs_conn_seq_start,
  	.next  = ip_vs_conn_seq_next,
  	.stop  = ip_vs_conn_seq_stop,
  	.show  = ip_vs_conn_seq_show,
  };
  
  static int ip_vs_conn_open(struct inode *inode, struct file *file)
  {
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1088
1089
  	return seq_open_net(inode, file, &ip_vs_conn_seq_ops,
  			    sizeof(struct ip_vs_iter_state));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090
  }
9a32144e9   Arjan van de Ven   [PATCH] mark stru...
1091
  static const struct file_operations ip_vs_conn_fops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1092
1093
1094
1095
  	.owner	 = THIS_MODULE,
  	.open    = ip_vs_conn_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
0f08190fe   Hans Schillstrom   IPVS: fix netns i...
1096
  	.release = seq_release_net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097
  };
7a4fbb1fa   Rumen G. Bogdanovski   [IPVS]: Flag sync...
1098

95c961747   Eric Dumazet   net: cleanup unsi...
1099
  static const char *ip_vs_origin_name(unsigned int flags)
7a4fbb1fa   Rumen G. Bogdanovski   [IPVS]: Flag sync...
1100
1101
1102
1103
1104
1105
1106
1107
1108
  {
  	if (flags & IP_VS_CONN_F_SYNC)
  		return "SYNC";
  	else
  		return "LOCAL";
  }
  
  static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
  {
f18ae7206   Julian Anastasov   ipvs: use the new...
1109
  	char dbuf[IP_VS_ADDRSTRLEN];
7a4fbb1fa   Rumen G. Bogdanovski   [IPVS]: Flag sync...
1110
1111
1112
1113
1114
1115
1116
  
  	if (v == SEQ_START_TOKEN)
  		seq_puts(seq,
     "Pro FromIP   FPrt ToIP     TPrt DestIP   DPrt State       Origin Expires
  ");
  	else {
  		const struct ip_vs_conn *cp = v;
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1117
  		struct net *net = seq_file_net(seq);
58dbc6f26   Eric W. Biederman   ipvs: Store ipvs ...
1118
  		if (!net_eq(cp->ipvs->net, net))
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1119
  			return 0;
7a4fbb1fa   Rumen G. Bogdanovski   [IPVS]: Flag sync...
1120

667a5f181   Vince Busam   IPVS: Convert pro...
1121
  #ifdef CONFIG_IP_VS_IPV6
f18ae7206   Julian Anastasov   ipvs: use the new...
1122
1123
1124
1125
1126
1127
1128
1129
  		if (cp->daf == AF_INET6)
  			snprintf(dbuf, sizeof(dbuf), "%pI6", &cp->daddr.in6);
  		else
  #endif
  			snprintf(dbuf, sizeof(dbuf), "%08X",
  				 ntohl(cp->daddr.ip));
  
  #ifdef CONFIG_IP_VS_IPV6
667a5f181   Vince Busam   IPVS: Convert pro...
1130
  		if (cp->af == AF_INET6)
f18ae7206   Julian Anastasov   ipvs: use the new...
1131
1132
1133
  			seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X "
  				"%s %04X %-11s %-6s %7lu
  ",
667a5f181   Vince Busam   IPVS: Convert pro...
1134
  				ip_vs_proto_name(cp->protocol),
38ff4fa49   Harvey Harrison   netfilter: replac...
1135
1136
  				&cp->caddr.in6, ntohs(cp->cport),
  				&cp->vaddr.in6, ntohs(cp->vport),
f18ae7206   Julian Anastasov   ipvs: use the new...
1137
  				dbuf, ntohs(cp->dport),
667a5f181   Vince Busam   IPVS: Convert pro...
1138
1139
1140
1141
1142
1143
1144
  				ip_vs_state_name(cp->protocol, cp->state),
  				ip_vs_origin_name(cp->flags),
  				(cp->timer.expires-jiffies)/HZ);
  		else
  #endif
  			seq_printf(seq,
  				"%-3s %08X %04X %08X %04X "
f18ae7206   Julian Anastasov   ipvs: use the new...
1145
1146
  				"%s %04X %-11s %-6s %7lu
  ",
7a4fbb1fa   Rumen G. Bogdanovski   [IPVS]: Flag sync...
1147
  				ip_vs_proto_name(cp->protocol),
e7ade46a5   Julius Volz   IPVS: Change IPVS...
1148
1149
  				ntohl(cp->caddr.ip), ntohs(cp->cport),
  				ntohl(cp->vaddr.ip), ntohs(cp->vport),
f18ae7206   Julian Anastasov   ipvs: use the new...
1150
  				dbuf, ntohs(cp->dport),
7a4fbb1fa   Rumen G. Bogdanovski   [IPVS]: Flag sync...
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
  				ip_vs_state_name(cp->protocol, cp->state),
  				ip_vs_origin_name(cp->flags),
  				(cp->timer.expires-jiffies)/HZ);
  	}
  	return 0;
  }
  
  static const struct seq_operations ip_vs_conn_sync_seq_ops = {
  	.start = ip_vs_conn_seq_start,
  	.next  = ip_vs_conn_seq_next,
  	.stop  = ip_vs_conn_seq_stop,
  	.show  = ip_vs_conn_sync_seq_show,
  };
  
  static int ip_vs_conn_sync_open(struct inode *inode, struct file *file)
  {
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1167
1168
  	return seq_open_net(inode, file, &ip_vs_conn_sync_seq_ops,
  			    sizeof(struct ip_vs_iter_state));
7a4fbb1fa   Rumen G. Bogdanovski   [IPVS]: Flag sync...
1169
1170
1171
1172
1173
1174
1175
  }
  
  static const struct file_operations ip_vs_conn_sync_fops = {
  	.owner	 = THIS_MODULE,
  	.open    = ip_vs_conn_sync_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
0f08190fe   Hans Schillstrom   IPVS: fix netns i...
1176
  	.release = seq_release_net,
7a4fbb1fa   Rumen G. Bogdanovski   [IPVS]: Flag sync...
1177
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
  #endif
  
  
  /*
   *      Randomly drop connection entries before running out of memory
   */
  static inline int todrop_entry(struct ip_vs_conn *cp)
  {
  	/*
  	 * The drop rate array needs tuning for real environments.
  	 * Called from timer bh only => no locking
  	 */
9b5b5cff9   Arjan van de Ven   [NET]: Add const ...
1190
  	static const char todrop_rate[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
  	static char todrop_counter[9] = {0};
  	int i;
  
  	/* if the conn entry hasn't lasted for 60 seconds, don't drop it.
  	   This will leave enough time for normal connection to get
  	   through. */
  	if (time_before(cp->timeout + jiffies, cp->timer.expires + 60*HZ))
  		return 0;
  
  	/* Don't drop the entry if its number of incoming packets is not
  	   located in [0, 8] */
  	i = atomic_read(&cp->in_pkts);
  	if (i > 8 || i < 0) return 0;
  
  	if (!todrop_rate[i]) return 0;
  	if (--todrop_counter[i] > 0) return 0;
  
  	todrop_counter[i] = todrop_rate[i];
  	return 1;
  }
698e2a8dc   Marco Angaroni   ipvs: make drop_e...
1211
1212
1213
1214
1215
1216
1217
1218
1219
  static inline bool ip_vs_conn_ops_mode(struct ip_vs_conn *cp)
  {
  	struct ip_vs_service *svc;
  
  	if (!cp->dest)
  		return false;
  	svc = rcu_dereference(cp->dest->svc);
  	return svc && (svc->flags & IP_VS_SVC_F_ONEPACKET);
  }
af9debd46   Julian Anastasov   [IPVS]: Add and r...
1220
  /* Called from keventd and must protect itself from softirqs */
423b55954   Eric W. Biederman   ipvs: Pass ipvs n...
1221
  void ip_vs_random_dropentry(struct netns_ipvs *ipvs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
1223
  {
  	int idx;
088339a57   Julian Anastasov   ipvs: convert con...
1224
  	struct ip_vs_conn *cp, *cp_c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225

a38e5e230   Simon Horman   ipvs: use cond_re...
1226
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
1228
1229
  	/*
  	 * Randomly scan 1/32 of the whole table every second
  	 */
6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
1230
  	for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) {
63862b5be   Aruna-Hewapathirane   net: replace macr...
1231
  		unsigned int hash = prandom_u32() & ip_vs_conn_tab_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232

088339a57   Julian Anastasov   ipvs: convert con...
1233
  		hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
423b55954   Eric W. Biederman   ipvs: Pass ipvs n...
1234
  			if (cp->ipvs != ipvs)
f6340ee0c   Hans Schillstrom   IPVS: netns, defe...
1235
  				continue;
698e2a8dc   Marco Angaroni   ipvs: make drop_e...
1236
1237
1238
1239
1240
1241
1242
1243
  			if (cp->flags & IP_VS_CONN_F_TEMPLATE) {
  				if (atomic_read(&cp->n_control) ||
  				    !ip_vs_conn_ops_mode(cp))
  					continue;
  				else
  					/* connection template of OPS */
  					goto try_drop;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
  			if (cp->protocol == IPPROTO_TCP) {
  				switch(cp->state) {
  				case IP_VS_TCP_S_SYN_RECV:
  				case IP_VS_TCP_S_SYNACK:
  					break;
  
  				case IP_VS_TCP_S_ESTABLISHED:
  					if (todrop_entry(cp))
  						break;
  					continue;
  
  				default:
  					continue;
  				}
acaac5d8b   Julian Anastasov   ipvs: drop SCTP c...
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
  			} else if (cp->protocol == IPPROTO_SCTP) {
  				switch (cp->state) {
  				case IP_VS_SCTP_S_INIT1:
  				case IP_VS_SCTP_S_INIT:
  					break;
  				case IP_VS_SCTP_S_ESTABLISHED:
  					if (todrop_entry(cp))
  						break;
  					continue;
  				default:
  					continue;
  				}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270
  			} else {
698e2a8dc   Marco Angaroni   ipvs: make drop_e...
1271
  try_drop:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1272
1273
1274
  				if (!todrop_entry(cp))
  					continue;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1275
1276
1277
  			IP_VS_DBG(4, "del connection
  ");
  			ip_vs_conn_expire_now(cp);
088339a57   Julian Anastasov   ipvs: convert con...
1278
1279
1280
  			cp_c = cp->control;
  			/* cp->control is valid only with reference to cp */
  			if (cp_c && __ip_vs_conn_get(cp)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281
1282
  				IP_VS_DBG(4, "del conn template
  ");
088339a57   Julian Anastasov   ipvs: convert con...
1283
1284
  				ip_vs_conn_expire_now(cp_c);
  				__ip_vs_conn_put(cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
  		}
a38e5e230   Simon Horman   ipvs: use cond_re...
1287
  		cond_resched_rcu();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1288
  	}
a38e5e230   Simon Horman   ipvs: use cond_re...
1289
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
1291
1292
1293
1294
1295
  }
  
  
  /*
   *      Flush all the connection entries in the ip_vs_conn_tab
   */
d889717aa   Eric W. Biederman   ipvs: Pass ipvs n...
1296
  static void ip_vs_conn_flush(struct netns_ipvs *ipvs)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
1298
  {
  	int idx;
088339a57   Julian Anastasov   ipvs: convert con...
1299
  	struct ip_vs_conn *cp, *cp_c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1300

a0840e2e1   Hans Schillstrom   IPVS: netns, ip_v...
1301
  flush_again:
a38e5e230   Simon Horman   ipvs: use cond_re...
1302
  	rcu_read_lock();
6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
1303
  	for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1304

088339a57   Julian Anastasov   ipvs: convert con...
1305
  		hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
58dbc6f26   Eric W. Biederman   ipvs: Store ipvs ...
1306
  			if (cp->ipvs != ipvs)
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1307
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1308
1309
1310
  			IP_VS_DBG(4, "del connection
  ");
  			ip_vs_conn_expire_now(cp);
088339a57   Julian Anastasov   ipvs: convert con...
1311
1312
1313
  			cp_c = cp->control;
  			/* cp->control is valid only with reference to cp */
  			if (cp_c && __ip_vs_conn_get(cp)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
1315
  				IP_VS_DBG(4, "del conn template
  ");
088339a57   Julian Anastasov   ipvs: convert con...
1316
1317
  				ip_vs_conn_expire_now(cp_c);
  				__ip_vs_conn_put(cp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1319
  		}
a38e5e230   Simon Horman   ipvs: use cond_re...
1320
  		cond_resched_rcu();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321
  	}
a38e5e230   Simon Horman   ipvs: use cond_re...
1322
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
1324
1325
  
  	/* the counter may be not NULL, because maybe some conn entries
  	   are run by slow timer handler or unhashed but still referred */
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1326
  	if (atomic_read(&ipvs->conn_count) != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
1328
1329
1330
  		schedule();
  		goto flush_again;
  	}
  }
61b1ab458   Hans Schillstrom   IPVS: netns, add ...
1331
1332
1333
  /*
   * per netns init and exit
   */
2f3edc6a5   Eric W. Biederman   ipvs: Pass ipvs n...
1334
  int __net_init ip_vs_conn_net_init(struct netns_ipvs *ipvs)
61b1ab458   Hans Schillstrom   IPVS: netns, add ...
1335
  {
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1336
  	atomic_set(&ipvs->conn_count, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337

92240e8dc   Simon Horman   ipvs: Remove poss...
1338
1339
1340
  	proc_create("ip_vs_conn", 0, ipvs->net->proc_net, &ip_vs_conn_fops);
  	proc_create("ip_vs_conn_sync", 0, ipvs->net->proc_net,
  		    &ip_vs_conn_sync_fops);
61b1ab458   Hans Schillstrom   IPVS: netns, add ...
1341
1342
  	return 0;
  }
2f3edc6a5   Eric W. Biederman   ipvs: Pass ipvs n...
1343
  void __net_exit ip_vs_conn_net_cleanup(struct netns_ipvs *ipvs)
61b1ab458   Hans Schillstrom   IPVS: netns, add ...
1344
  {
6e67e586e   Hans Schillstrom   IPVS: netns, conn...
1345
  	/* flush all the connection entries first */
d889717aa   Eric W. Biederman   ipvs: Pass ipvs n...
1346
  	ip_vs_conn_flush(ipvs);
92240e8dc   Simon Horman   ipvs: Remove poss...
1347
1348
  	remove_proc_entry("ip_vs_conn", ipvs->net->proc_net);
  	remove_proc_entry("ip_vs_conn_sync", ipvs->net->proc_net);
61b1ab458   Hans Schillstrom   IPVS: netns, add ...
1349
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1350

048cf48b8   Sven Wegener   ipvs: Annotate in...
1351
  int __init ip_vs_conn_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
1353
  {
  	int idx;
6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
1354
1355
1356
  	/* Compute size and mask */
  	ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
  	ip_vs_conn_tab_mask = ip_vs_conn_tab_size - 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357
1358
1359
  	/*
  	 * Allocate the connection hash table and initialize its list heads
  	 */
731109e78   Changli Gao   ipvs: use hlist i...
1360
  	ip_vs_conn_tab = vmalloc(ip_vs_conn_tab_size * sizeof(*ip_vs_conn_tab));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
1362
1363
1364
1365
1366
  	if (!ip_vs_conn_tab)
  		return -ENOMEM;
  
  	/* Allocate ip_vs_conn slab cache */
  	ip_vs_conn_cachep = kmem_cache_create("ip_vs_conn",
  					      sizeof(struct ip_vs_conn), 0,
20c2df83d   Paul Mundt   mm: Remove slab d...
1367
  					      SLAB_HWCACHE_ALIGN, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
1369
1370
1371
  	if (!ip_vs_conn_cachep) {
  		vfree(ip_vs_conn_tab);
  		return -ENOMEM;
  	}
1e3e238e9   Hannes Eder   IPVS: use pr_err ...
1372
1373
1374
  	pr_info("Connection hash table configured "
  		"(size=%d, memory=%ldKbytes)
  ",
6f7edb488   Catalin(ux) M. BOIE   IPVS: Allow boot ...
1375
1376
  		ip_vs_conn_tab_size,
  		(long)(ip_vs_conn_tab_size*sizeof(struct list_head))/1024);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
1378
1379
  	IP_VS_DBG(0, "Each connection entry needs %Zd bytes at least
  ",
  		  sizeof(struct ip_vs_conn));
731109e78   Changli Gao   ipvs: use hlist i...
1380
1381
  	for (idx = 0; idx < ip_vs_conn_tab_size; idx++)
  		INIT_HLIST_HEAD(&ip_vs_conn_tab[idx]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
1383
  
  	for (idx = 0; idx < CT_LOCKARRAY_SIZE; idx++)  {
088339a57   Julian Anastasov   ipvs: convert con...
1384
  		spin_lock_init(&__ip_vs_conntbl_lock_array[idx].l);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
1387
  	/* calculate the random value for connection hash */
  	get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
7a4f0761f   Hans Schillstrom   IPVS: init and cl...
1388
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1389
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
1391
  void ip_vs_conn_cleanup(void)
  {
088339a57   Julian Anastasov   ipvs: convert con...
1392
1393
  	/* Wait all ip_vs_conn_rcu_free() callbacks to complete */
  	rcu_barrier();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
1395
  	/* Release the empty cache */
  	kmem_cache_destroy(ip_vs_conn_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
1397
  	vfree(ip_vs_conn_tab);
  }