diff options
author | Simon Horman <horms@verge.net.au> | 2010-08-22 08:37:53 -0400 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2010-10-04 09:45:24 -0400 |
commit | 85999283a21ab2dd37427fdd8c8e8af57223977c (patch) | |
tree | a78ba043c23182d47cfe473a9a829d8608e2d526 /net | |
parent | 2fabf35bfcd89445c54cf1e6a5437dd3cf924a92 (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.c | 67 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 36 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_sync.c | 17 |
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 | ||
151 | static 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 | |||
172 | static 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 | ||
179 | static inline int | ||
180 | ip_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 | */ |
187 | static struct ip_vs_conn * | 200 | static struct ip_vs_conn * |
188 | ip_vs_sched_persist(struct ip_vs_service *svc, | 201 | ip_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, ¶m); | 272 | vaddr, vport, ¶m)) |
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(¶m, &dest->addr, dport, | 296 | ct = ip_vs_conn_new(¶m, &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 | */ |
324 | struct ip_vs_conn * | 346 | struct ip_vs_conn * |
325 | ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 347 | ip_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 | ||
291 | static inline int | ||
292 | ip_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, ¶m); | 389 | s->vport, ¶m)) { |
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(¶m); | 394 | cp = ip_vs_conn_in_get(¶m); |
382 | else | 395 | else |