aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2010-08-22 08:37:53 -0400
committerSimon Horman <horms@verge.net.au>2010-10-04 09:45:24 -0400
commit85999283a21ab2dd37427fdd8c8e8af57223977c (patch)
treea78ba043c23182d47cfe473a9a829d8608e2d526 /net
parent2fabf35bfcd89445c54cf1e6a5437dd3cf924a92 (diff)
IPVS: Add struct ip_vs_pe
Signed-off-by: Simon Horman <horms@verge.net.au> Acked-by: Julian Anastasov <ja@ssi.bg>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c67
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c36
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c17
3 files changed, 100 insertions, 20 deletions
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index deeb906a797b..06da21e97405 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -148,6 +148,42 @@ static unsigned int ip_vs_conn_hashkey(int af, unsigned proto,
148 & ip_vs_conn_tab_mask; 148 & ip_vs_conn_tab_mask;
149} 149}
150 150
151static unsigned int ip_vs_conn_hashkey_param(const struct ip_vs_conn_param *p,
152 bool inverse)
153{
154 const union nf_inet_addr *addr;
155 __be16 port;
156
157 if (p->pe && p->pe->hashkey_raw)
158 return p->pe->hashkey_raw(p, ip_vs_conn_rnd, inverse) &
159 ip_vs_conn_tab_mask;
160
161 if (likely(!inverse)) {
162 addr = p->caddr;
163 port = p->cport;
164 } else {
165 addr = p->vaddr;
166 port = p->vport;
167 }
168
169 return ip_vs_conn_hashkey(p->af, p->protocol, addr, port);
170}
171
172static unsigned int ip_vs_conn_hashkey_conn(const struct ip_vs_conn *cp)
173{
174 struct ip_vs_conn_param p;
175
176 ip_vs_conn_fill_param(cp->af, cp->protocol, &cp->caddr, cp->cport,
177 NULL, 0, &p);
178
179 if (cp->dest && cp->dest->svc->pe) {
180 p.pe = cp->dest->svc->pe;
181 p.pe_data = cp->pe_data;
182 p.pe_data_len = cp->pe_data_len;
183 }
184
185 return ip_vs_conn_hashkey_param(&p, false);
186}
151 187
152/* 188/*
153 * Hashes ip_vs_conn in ip_vs_conn_tab by proto,addr,port. 189 * Hashes ip_vs_conn in ip_vs_conn_tab by proto,addr,port.
@@ -162,7 +198,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
162 return 0; 198 return 0;
163 199
164 /* Hash by protocol, client address and port */ 200 /* Hash by protocol, client address and port */
165 hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport); 201 hash = ip_vs_conn_hashkey_conn(cp);
166 202
167 ct_write_lock(hash); 203 ct_write_lock(hash);
168 spin_lock(&cp->lock); 204 spin_lock(&cp->lock);
@@ -195,7 +231,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
195 int ret; 231 int ret;
196 232
197 /* unhash it and decrease its reference counter */ 233 /* unhash it and decrease its reference counter */
198 hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport); 234 hash = ip_vs_conn_hashkey_conn(cp);
199 235
200 ct_write_lock(hash); 236 ct_write_lock(hash);
201 spin_lock(&cp->lock); 237 spin_lock(&cp->lock);
@@ -227,7 +263,7 @@ __ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
227 unsigned hash; 263 unsigned hash;
228 struct ip_vs_conn *cp; 264 struct ip_vs_conn *cp;
229 265
230 hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport); 266 hash = ip_vs_conn_hashkey_param(p, false);
231 267
232 ct_read_lock(hash); 268 ct_read_lock(hash);
233 269
@@ -312,11 +348,17 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
312 unsigned hash; 348 unsigned hash;
313 struct ip_vs_conn *cp; 349 struct ip_vs_conn *cp;
314 350
315 hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport); 351 hash = ip_vs_conn_hashkey_param(p, false);
316 352
317 ct_read_lock(hash); 353 ct_read_lock(hash);
318 354
319 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { 355 list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
356 if (p->pe && p->pe->ct_match) {
357 if (p->pe->ct_match(p, cp))
358 goto out;
359 continue;
360 }
361
320 if (cp->af == p->af && 362 if (cp->af == p->af &&
321 ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) && 363 ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
322 /* protocol should only be IPPROTO_IP if 364 /* protocol should only be IPPROTO_IP if
@@ -325,15 +367,14 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
325 p->af, p->vaddr, &cp->vaddr) && 367 p->af, p->vaddr, &cp->vaddr) &&
326 p->cport == cp->cport && p->vport == cp->vport && 368 p->cport == cp->cport && p->vport == cp->vport &&
327 cp->flags & IP_VS_CONN_F_TEMPLATE && 369 cp->flags & IP_VS_CONN_F_TEMPLATE &&
328 p->protocol == cp->protocol) { 370 p->protocol == cp->protocol)
329 /* HIT */
330 atomic_inc(&cp->refcnt);
331 goto out; 371 goto out;
332 }
333 } 372 }
334 cp = NULL; 373 cp = NULL;
335 374
336 out: 375 out:
376 if (cp)
377 atomic_inc(&cp->refcnt);
337 ct_read_unlock(hash); 378 ct_read_unlock(hash);
338 379
339 IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n", 380 IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n",
@@ -357,7 +398,7 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
357 /* 398 /*
358 * Check for "full" addressed entries 399 * Check for "full" addressed entries
359 */ 400 */
360 hash = ip_vs_conn_hashkey(p->af, p->protocol, p->vaddr, p->vport); 401 hash = ip_vs_conn_hashkey_param(p, true);
361 402
362 ct_read_lock(hash); 403 ct_read_lock(hash);
363 404
@@ -722,6 +763,7 @@ static void ip_vs_conn_expire(unsigned long data)
722 if (cp->flags & IP_VS_CONN_F_NFCT) 763 if (cp->flags & IP_VS_CONN_F_NFCT)
723 ip_vs_conn_drop_conntrack(cp); 764 ip_vs_conn_drop_conntrack(cp);
724 765
766 kfree(cp->pe_data);
725 if (unlikely(cp->app != NULL)) 767 if (unlikely(cp->app != NULL))
726 ip_vs_unbind_app(cp); 768 ip_vs_unbind_app(cp);
727 ip_vs_unbind_dest(cp); 769 ip_vs_unbind_dest(cp);
@@ -782,6 +824,10 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
782 &cp->daddr, daddr); 824 &cp->daddr, daddr);
783 cp->dport = dport; 825 cp->dport = dport;
784 cp->flags = flags; 826 cp->flags = flags;
827 if (flags & IP_VS_CONN_F_TEMPLATE && p->pe_data) {
828 cp->pe_data = p->pe_data;
829 cp->pe_data_len = p->pe_data_len;
830 }
785 spin_lock_init(&cp->lock); 831 spin_lock_init(&cp->lock);
786 832
787 /* 833 /*
@@ -832,7 +878,6 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
832 return cp; 878 return cp;
833} 879}
834 880
835
836/* 881/*
837 * /proc/net/ip_vs_conn entries 882 * /proc/net/ip_vs_conn entries
838 */ 883 */
@@ -848,7 +893,7 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
848 list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) { 893 list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
849 if (pos-- == 0) { 894 if (pos-- == 0) {
850 seq->private = &ip_vs_conn_tab[idx]; 895 seq->private = &ip_vs_conn_tab[idx];
851 return cp; 896 return cp;
852 } 897 }
853 } 898 }
854 ct_read_unlock_bh(idx); 899 ct_read_unlock_bh(idx);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 87602a62458e..ab9889380496 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -176,6 +176,19 @@ ip_vs_set_state(struct ip_vs_conn *cp, int direction,
176 return pp->state_transition(cp, direction, skb, pp); 176 return pp->state_transition(cp, direction, skb, pp);
177} 177}
178 178
179static inline int
180ip_vs_conn_fill_param_persist(const struct ip_vs_service *svc,
181 struct sk_buff *skb, int protocol,
182 const union nf_inet_addr *caddr, __be16 cport,
183 const union nf_inet_addr *vaddr, __be16 vport,
184 struct ip_vs_conn_param *p)
185{
186 ip_vs_conn_fill_param(svc->af, protocol, caddr, cport, vaddr, vport, p);
187 p->pe = svc->pe;
188 if (p->pe && p->pe->fill_param)
189 return p->pe->fill_param(p, skb);
190 return 0;
191}
179 192
180/* 193/*
181 * IPVS persistent scheduling function 194 * IPVS persistent scheduling function
@@ -186,7 +199,7 @@ ip_vs_set_state(struct ip_vs_conn *cp, int direction,
186 */ 199 */
187static struct ip_vs_conn * 200static struct ip_vs_conn *
188ip_vs_sched_persist(struct ip_vs_service *svc, 201ip_vs_sched_persist(struct ip_vs_service *svc,
189 const struct sk_buff *skb, 202 struct sk_buff *skb,
190 __be16 ports[2]) 203 __be16 ports[2])
191{ 204{
192 struct ip_vs_conn *cp = NULL; 205 struct ip_vs_conn *cp = NULL;
@@ -255,8 +268,9 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
255 vaddr = &fwmark; 268 vaddr = &fwmark;
256 } 269 }
257 } 270 }
258 ip_vs_conn_fill_param(svc->af, protocol, &snet, 0, 271 if (ip_vs_conn_fill_param_persist(svc, skb, protocol, &snet, 0,
259 vaddr, vport, &param); 272 vaddr, vport, &param))
273 return NULL;
260 } 274 }
261 275
262 /* Check if a template already exists */ 276 /* Check if a template already exists */
@@ -268,22 +282,30 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
268 dest = svc->scheduler->schedule(svc, skb); 282 dest = svc->scheduler->schedule(svc, skb);
269 if (!dest) { 283 if (!dest) {
270 IP_VS_DBG(1, "p-schedule: no dest found.\n"); 284 IP_VS_DBG(1, "p-schedule: no dest found.\n");
285 kfree(param.pe_data);
271 return NULL; 286 return NULL;
272 } 287 }
273 288
274 if (ports[1] == svc->port && svc->port != FTPPORT) 289 if (ports[1] == svc->port && svc->port != FTPPORT)
275 dport = dest->port; 290 dport = dest->port;
276 291
277 /* Create a template */ 292 /* Create a template
293 * This adds param.pe_data to the template,
294 * and thus param.pe_data will be destroyed
295 * when the template expires */
278 ct = ip_vs_conn_new(&param, &dest->addr, dport, 296 ct = ip_vs_conn_new(&param, &dest->addr, dport,
279 IP_VS_CONN_F_TEMPLATE, dest); 297 IP_VS_CONN_F_TEMPLATE, dest);
280 if (ct == NULL) 298 if (ct == NULL) {
299 kfree(param.pe_data);
281 return NULL; 300 return NULL;
301 }
282 302
283 ct->timeout = svc->timeout; 303 ct->timeout = svc->timeout;
284 } else 304 } else {
285 /* set destination with the found template */ 305 /* set destination with the found template */
286 dest = ct->dest; 306 dest = ct->dest;
307 kfree(param.pe_data);
308 }
287 309
288 dport = ports[1]; 310 dport = ports[1];
289 if (dport == svc->port && dest->port) 311 if (dport == svc->port && dest->port)
@@ -322,7 +344,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
322 * Protocols supported: TCP, UDP 344 * Protocols supported: TCP, UDP
323 */ 345 */
324struct ip_vs_conn * 346struct ip_vs_conn *
325ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) 347ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb)
326{ 348{
327 struct ip_vs_conn *cp = NULL; 349 struct ip_vs_conn *cp = NULL;
328 struct ip_vs_iphdr iph; 350 struct ip_vs_iphdr iph;
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index f68631f75f09..ab85aedea17e 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -288,6 +288,16 @@ void ip_vs_sync_conn(struct ip_vs_conn *cp)
288 ip_vs_sync_conn(cp->control); 288 ip_vs_sync_conn(cp->control);
289} 289}
290 290
291static inline int
292ip_vs_conn_fill_param_sync(int af, int protocol,
293 const union nf_inet_addr *caddr, __be16 cport,
294 const union nf_inet_addr *vaddr, __be16 vport,
295 struct ip_vs_conn_param *p)
296{
297 /* XXX: Need to take into account persistence engine */
298 ip_vs_conn_fill_param(af, protocol, caddr, cport, vaddr, vport, p);
299 return 0;
300}
291 301
292/* 302/*
293 * Process received multicast message and create the corresponding 303 * Process received multicast message and create the corresponding
@@ -372,11 +382,14 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
372 } 382 }
373 383
374 { 384 {
375 ip_vs_conn_fill_param(AF_INET, s->protocol, 385 if (ip_vs_conn_fill_param_sync(AF_INET, s->protocol,
376 (union nf_inet_addr *)&s->caddr, 386 (union nf_inet_addr *)&s->caddr,
377 s->cport, 387 s->cport,
378 (union nf_inet_addr *)&s->vaddr, 388 (union nf_inet_addr *)&s->vaddr,
379 s->vport, &param); 389 s->vport, &param)) {
390 pr_err("ip_vs_conn_fill_param_sync failed");
391 return;
392 }
380 if (!(flags & IP_VS_CONN_F_TEMPLATE)) 393 if (!(flags & IP_VS_CONN_F_TEMPLATE))
381 cp = ip_vs_conn_in_get(&param); 394 cp = ip_vs_conn_in_get(&param);
382 else 395 else