diff options
author | Julius Volz <julius.volz@gmail.com> | 2008-11-03 20:08:28 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-03 20:08:28 -0500 |
commit | 445483758e35e0aaff5256d1b104a346ba77aafe (patch) | |
tree | ddbc0fe710400b1b9cffdb9ca80eaadfc8770226 /net | |
parent | fa228b3fcb724ce2281a61737e09a8afa4fed542 (diff) |
IPVS: Add IPv6 support to LBLC/LBLCR schedulers
Add IPv6 support to LBLC and LBLCR schedulers. These were the last
schedulers without IPv6 support, but we might want to keep the
supports_ipv6 flag in the case of future schedulers without IPv6
support.
Signed-off-by: Julius Volz <julius.volz@gmail.com>
Acked-by: Simon Horman <horms@verge.net.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/ipvs/ip_vs_lblc.c | 63 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_lblcr.c | 90 |
2 files changed, 92 insertions, 61 deletions
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 035d4c3e8646..135a59454f1f 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c | |||
@@ -86,7 +86,8 @@ static int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ; | |||
86 | */ | 86 | */ |
87 | struct ip_vs_lblc_entry { | 87 | struct ip_vs_lblc_entry { |
88 | struct list_head list; | 88 | struct list_head list; |
89 | __be32 addr; /* destination IP address */ | 89 | int af; /* address family */ |
90 | union nf_inet_addr addr; /* destination IP address */ | ||
90 | struct ip_vs_dest *dest; /* real server (cache) */ | 91 | struct ip_vs_dest *dest; /* real server (cache) */ |
91 | unsigned long lastuse; /* last used time */ | 92 | unsigned long lastuse; /* last used time */ |
92 | }; | 93 | }; |
@@ -137,9 +138,17 @@ static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en) | |||
137 | /* | 138 | /* |
138 | * Returns hash value for IPVS LBLC entry | 139 | * Returns hash value for IPVS LBLC entry |
139 | */ | 140 | */ |
140 | static inline unsigned ip_vs_lblc_hashkey(__be32 addr) | 141 | static inline unsigned |
142 | ip_vs_lblc_hashkey(int af, const union nf_inet_addr *addr) | ||
141 | { | 143 | { |
142 | return (ntohl(addr)*2654435761UL) & IP_VS_LBLC_TAB_MASK; | 144 | __be32 addr_fold = addr->ip; |
145 | |||
146 | #ifdef CONFIG_IP_VS_IPV6 | ||
147 | if (af == AF_INET6) | ||
148 | addr_fold = addr->ip6[0]^addr->ip6[1]^ | ||
149 | addr->ip6[2]^addr->ip6[3]; | ||
150 | #endif | ||
151 | return (ntohl(addr_fold)*2654435761UL) & IP_VS_LBLC_TAB_MASK; | ||
143 | } | 152 | } |
144 | 153 | ||
145 | 154 | ||
@@ -150,7 +159,7 @@ static inline unsigned ip_vs_lblc_hashkey(__be32 addr) | |||
150 | static void | 159 | static void |
151 | ip_vs_lblc_hash(struct ip_vs_lblc_table *tbl, struct ip_vs_lblc_entry *en) | 160 | ip_vs_lblc_hash(struct ip_vs_lblc_table *tbl, struct ip_vs_lblc_entry *en) |
152 | { | 161 | { |
153 | unsigned hash = ip_vs_lblc_hashkey(en->addr); | 162 | unsigned hash = ip_vs_lblc_hashkey(en->af, &en->addr); |
154 | 163 | ||
155 | list_add(&en->list, &tbl->bucket[hash]); | 164 | list_add(&en->list, &tbl->bucket[hash]); |
156 | atomic_inc(&tbl->entries); | 165 | atomic_inc(&tbl->entries); |
@@ -162,13 +171,14 @@ ip_vs_lblc_hash(struct ip_vs_lblc_table *tbl, struct ip_vs_lblc_entry *en) | |||
162 | * lock | 171 | * lock |
163 | */ | 172 | */ |
164 | static inline struct ip_vs_lblc_entry * | 173 | static inline struct ip_vs_lblc_entry * |
165 | ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __be32 addr) | 174 | ip_vs_lblc_get(int af, struct ip_vs_lblc_table *tbl, |
175 | const union nf_inet_addr *addr) | ||
166 | { | 176 | { |
167 | unsigned hash = ip_vs_lblc_hashkey(addr); | 177 | unsigned hash = ip_vs_lblc_hashkey(af, addr); |
168 | struct ip_vs_lblc_entry *en; | 178 | struct ip_vs_lblc_entry *en; |
169 | 179 | ||
170 | list_for_each_entry(en, &tbl->bucket[hash], list) | 180 | list_for_each_entry(en, &tbl->bucket[hash], list) |
171 | if (en->addr == addr) | 181 | if (ip_vs_addr_equal(af, &en->addr, addr)) |
172 | return en; | 182 | return en; |
173 | 183 | ||
174 | return NULL; | 184 | return NULL; |
@@ -180,12 +190,12 @@ ip_vs_lblc_get(struct ip_vs_lblc_table *tbl, __be32 addr) | |||
180 | * address to a server. Called under write lock. | 190 | * address to a server. Called under write lock. |
181 | */ | 191 | */ |
182 | static inline struct ip_vs_lblc_entry * | 192 | static inline struct ip_vs_lblc_entry * |
183 | ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, __be32 daddr, | 193 | ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr, |
184 | struct ip_vs_dest *dest) | 194 | struct ip_vs_dest *dest) |
185 | { | 195 | { |
186 | struct ip_vs_lblc_entry *en; | 196 | struct ip_vs_lblc_entry *en; |
187 | 197 | ||
188 | en = ip_vs_lblc_get(tbl, daddr); | 198 | en = ip_vs_lblc_get(dest->af, tbl, daddr); |
189 | if (!en) { | 199 | if (!en) { |
190 | en = kmalloc(sizeof(*en), GFP_ATOMIC); | 200 | en = kmalloc(sizeof(*en), GFP_ATOMIC); |
191 | if (!en) { | 201 | if (!en) { |
@@ -193,7 +203,8 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, __be32 daddr, | |||
193 | return NULL; | 203 | return NULL; |
194 | } | 204 | } |
195 | 205 | ||
196 | en->addr = daddr; | 206 | en->af = dest->af; |
207 | ip_vs_addr_copy(dest->af, &en->addr, daddr); | ||
197 | en->lastuse = jiffies; | 208 | en->lastuse = jiffies; |
198 | 209 | ||
199 | atomic_inc(&dest->refcnt); | 210 | atomic_inc(&dest->refcnt); |
@@ -369,7 +380,7 @@ static int ip_vs_lblc_done_svc(struct ip_vs_service *svc) | |||
369 | 380 | ||
370 | 381 | ||
371 | static inline struct ip_vs_dest * | 382 | static inline struct ip_vs_dest * |
372 | __ip_vs_lblc_schedule(struct ip_vs_service *svc, struct iphdr *iph) | 383 | __ip_vs_lblc_schedule(struct ip_vs_service *svc) |
373 | { | 384 | { |
374 | struct ip_vs_dest *dest, *least; | 385 | struct ip_vs_dest *dest, *least; |
375 | int loh, doh; | 386 | int loh, doh; |
@@ -420,12 +431,13 @@ __ip_vs_lblc_schedule(struct ip_vs_service *svc, struct iphdr *iph) | |||
420 | } | 431 | } |
421 | } | 432 | } |
422 | 433 | ||
423 | IP_VS_DBG(6, "LBLC: server %pI4:%d " | 434 | IP_VS_DBG_BUF(6, "LBLC: server %s:%d " |
424 | "activeconns %d refcnt %d weight %d overhead %d\n", | 435 | "activeconns %d refcnt %d weight %d overhead %d\n", |
425 | &least->addr.ip, ntohs(least->port), | 436 | IP_VS_DBG_ADDR(least->af, &least->addr), |
426 | atomic_read(&least->activeconns), | 437 | ntohs(least->port), |
427 | atomic_read(&least->refcnt), | 438 | atomic_read(&least->activeconns), |
428 | atomic_read(&least->weight), loh); | 439 | atomic_read(&least->refcnt), |
440 | atomic_read(&least->weight), loh); | ||
429 | 441 | ||
430 | return least; | 442 | return least; |
431 | } | 443 | } |
@@ -459,15 +471,17 @@ static struct ip_vs_dest * | |||
459 | ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 471 | ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) |
460 | { | 472 | { |
461 | struct ip_vs_lblc_table *tbl = svc->sched_data; | 473 | struct ip_vs_lblc_table *tbl = svc->sched_data; |
462 | struct iphdr *iph = ip_hdr(skb); | 474 | struct ip_vs_iphdr iph; |
463 | struct ip_vs_dest *dest = NULL; | 475 | struct ip_vs_dest *dest = NULL; |
464 | struct ip_vs_lblc_entry *en; | 476 | struct ip_vs_lblc_entry *en; |
465 | 477 | ||
478 | ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph); | ||
479 | |||
466 | IP_VS_DBG(6, "ip_vs_lblc_schedule(): Scheduling...\n"); | 480 | IP_VS_DBG(6, "ip_vs_lblc_schedule(): Scheduling...\n"); |
467 | 481 | ||
468 | /* First look in our cache */ | 482 | /* First look in our cache */ |
469 | read_lock(&svc->sched_lock); | 483 | read_lock(&svc->sched_lock); |
470 | en = ip_vs_lblc_get(tbl, iph->daddr); | 484 | en = ip_vs_lblc_get(svc->af, tbl, &iph.daddr); |
471 | if (en) { | 485 | if (en) { |
472 | /* We only hold a read lock, but this is atomic */ | 486 | /* We only hold a read lock, but this is atomic */ |
473 | en->lastuse = jiffies; | 487 | en->lastuse = jiffies; |
@@ -491,7 +505,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | |||
491 | goto out; | 505 | goto out; |
492 | 506 | ||
493 | /* No cache entry or it is invalid, time to schedule */ | 507 | /* No cache entry or it is invalid, time to schedule */ |
494 | dest = __ip_vs_lblc_schedule(svc, iph); | 508 | dest = __ip_vs_lblc_schedule(svc); |
495 | if (!dest) { | 509 | if (!dest) { |
496 | IP_VS_DBG(1, "no destination available\n"); | 510 | IP_VS_DBG(1, "no destination available\n"); |
497 | return NULL; | 511 | return NULL; |
@@ -499,12 +513,13 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | |||
499 | 513 | ||
500 | /* If we fail to create a cache entry, we'll just use the valid dest */ | 514 | /* If we fail to create a cache entry, we'll just use the valid dest */ |
501 | write_lock(&svc->sched_lock); | 515 | write_lock(&svc->sched_lock); |
502 | ip_vs_lblc_new(tbl, iph->daddr, dest); | 516 | ip_vs_lblc_new(tbl, &iph.daddr, dest); |
503 | write_unlock(&svc->sched_lock); | 517 | write_unlock(&svc->sched_lock); |
504 | 518 | ||
505 | out: | 519 | out: |
506 | IP_VS_DBG(6, "LBLC: destination IP address %pI4 --> server %pI4:%d\n", | 520 | IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n", |
507 | &iph->daddr, &dest->addr.ip, ntohs(dest->port)); | 521 | IP_VS_DBG_ADDR(svc->af, &iph.daddr), |
522 | IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); | ||
508 | 523 | ||
509 | return dest; | 524 | return dest; |
510 | } | 525 | } |
@@ -520,7 +535,7 @@ static struct ip_vs_scheduler ip_vs_lblc_scheduler = | |||
520 | .module = THIS_MODULE, | 535 | .module = THIS_MODULE, |
521 | .n_list = LIST_HEAD_INIT(ip_vs_lblc_scheduler.n_list), | 536 | .n_list = LIST_HEAD_INIT(ip_vs_lblc_scheduler.n_list), |
522 | #ifdef CONFIG_IP_VS_IPV6 | 537 | #ifdef CONFIG_IP_VS_IPV6 |
523 | .supports_ipv6 = 0, | 538 | .supports_ipv6 = 1, |
524 | #endif | 539 | #endif |
525 | .init_service = ip_vs_lblc_init_svc, | 540 | .init_service = ip_vs_lblc_init_svc, |
526 | .done_service = ip_vs_lblc_done_svc, | 541 | .done_service = ip_vs_lblc_done_svc, |
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index cceeff6a9f74..4d6534a71b8f 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c | |||
@@ -202,12 +202,13 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) | |||
202 | } | 202 | } |
203 | } | 203 | } |
204 | 204 | ||
205 | IP_VS_DBG(6, "ip_vs_dest_set_min: server %pI4:%d " | 205 | IP_VS_DBG_BUF(6, "ip_vs_dest_set_min: server %s:%d " |
206 | "activeconns %d refcnt %d weight %d overhead %d\n", | 206 | "activeconns %d refcnt %d weight %d overhead %d\n", |
207 | &least->addr.ip, ntohs(least->port), | 207 | IP_VS_DBG_ADDR(least->af, &least->addr), |
208 | atomic_read(&least->activeconns), | 208 | ntohs(least->port), |
209 | atomic_read(&least->refcnt), | 209 | atomic_read(&least->activeconns), |
210 | atomic_read(&least->weight), loh); | 210 | atomic_read(&least->refcnt), |
211 | atomic_read(&least->weight), loh); | ||
211 | return least; | 212 | return least; |
212 | } | 213 | } |
213 | 214 | ||
@@ -248,12 +249,12 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) | |||
248 | } | 249 | } |
249 | } | 250 | } |
250 | 251 | ||
251 | IP_VS_DBG(6, "ip_vs_dest_set_max: server %pI4:%d " | 252 | IP_VS_DBG_BUF(6, "ip_vs_dest_set_max: server %s:%d " |
252 | "activeconns %d refcnt %d weight %d overhead %d\n", | 253 | "activeconns %d refcnt %d weight %d overhead %d\n", |
253 | &most->addr.ip, ntohs(most->port), | 254 | IP_VS_DBG_ADDR(most->af, &most->addr), ntohs(most->port), |
254 | atomic_read(&most->activeconns), | 255 | atomic_read(&most->activeconns), |
255 | atomic_read(&most->refcnt), | 256 | atomic_read(&most->refcnt), |
256 | atomic_read(&most->weight), moh); | 257 | atomic_read(&most->weight), moh); |
257 | return most; | 258 | return most; |
258 | } | 259 | } |
259 | 260 | ||
@@ -264,7 +265,8 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) | |||
264 | */ | 265 | */ |
265 | struct ip_vs_lblcr_entry { | 266 | struct ip_vs_lblcr_entry { |
266 | struct list_head list; | 267 | struct list_head list; |
267 | __be32 addr; /* destination IP address */ | 268 | int af; /* address family */ |
269 | union nf_inet_addr addr; /* destination IP address */ | ||
268 | struct ip_vs_dest_set set; /* destination server set */ | 270 | struct ip_vs_dest_set set; /* destination server set */ |
269 | unsigned long lastuse; /* last used time */ | 271 | unsigned long lastuse; /* last used time */ |
270 | }; | 272 | }; |
@@ -311,9 +313,17 @@ static inline void ip_vs_lblcr_free(struct ip_vs_lblcr_entry *en) | |||
311 | /* | 313 | /* |
312 | * Returns hash value for IPVS LBLCR entry | 314 | * Returns hash value for IPVS LBLCR entry |
313 | */ | 315 | */ |
314 | static inline unsigned ip_vs_lblcr_hashkey(__be32 addr) | 316 | static inline unsigned |
317 | ip_vs_lblcr_hashkey(int af, const union nf_inet_addr *addr) | ||
315 | { | 318 | { |
316 | return (ntohl(addr)*2654435761UL) & IP_VS_LBLCR_TAB_MASK; | 319 | __be32 addr_fold = addr->ip; |
320 | |||
321 | #ifdef CONFIG_IP_VS_IPV6 | ||
322 | if (af == AF_INET6) | ||
323 | addr_fold = addr->ip6[0]^addr->ip6[1]^ | ||
324 | addr->ip6[2]^addr->ip6[3]; | ||
325 | #endif | ||
326 | return (ntohl(addr_fold)*2654435761UL) & IP_VS_LBLCR_TAB_MASK; | ||
317 | } | 327 | } |
318 | 328 | ||
319 | 329 | ||
@@ -324,7 +334,7 @@ static inline unsigned ip_vs_lblcr_hashkey(__be32 addr) | |||
324 | static void | 334 | static void |
325 | ip_vs_lblcr_hash(struct ip_vs_lblcr_table *tbl, struct ip_vs_lblcr_entry *en) | 335 | ip_vs_lblcr_hash(struct ip_vs_lblcr_table *tbl, struct ip_vs_lblcr_entry *en) |
326 | { | 336 | { |
327 | unsigned hash = ip_vs_lblcr_hashkey(en->addr); | 337 | unsigned hash = ip_vs_lblcr_hashkey(en->af, &en->addr); |
328 | 338 | ||
329 | list_add(&en->list, &tbl->bucket[hash]); | 339 | list_add(&en->list, &tbl->bucket[hash]); |
330 | atomic_inc(&tbl->entries); | 340 | atomic_inc(&tbl->entries); |
@@ -336,13 +346,14 @@ ip_vs_lblcr_hash(struct ip_vs_lblcr_table *tbl, struct ip_vs_lblcr_entry *en) | |||
336 | * read lock. | 346 | * read lock. |
337 | */ | 347 | */ |
338 | static inline struct ip_vs_lblcr_entry * | 348 | static inline struct ip_vs_lblcr_entry * |
339 | ip_vs_lblcr_get(struct ip_vs_lblcr_table *tbl, __be32 addr) | 349 | ip_vs_lblcr_get(int af, struct ip_vs_lblcr_table *tbl, |
350 | const union nf_inet_addr *addr) | ||
340 | { | 351 | { |
341 | unsigned hash = ip_vs_lblcr_hashkey(addr); | 352 | unsigned hash = ip_vs_lblcr_hashkey(af, addr); |
342 | struct ip_vs_lblcr_entry *en; | 353 | struct ip_vs_lblcr_entry *en; |
343 | 354 | ||
344 | list_for_each_entry(en, &tbl->bucket[hash], list) | 355 | list_for_each_entry(en, &tbl->bucket[hash], list) |
345 | if (en->addr == addr) | 356 | if (ip_vs_addr_equal(af, &en->addr, addr)) |
346 | return en; | 357 | return en; |
347 | 358 | ||
348 | return NULL; | 359 | return NULL; |
@@ -354,12 +365,12 @@ ip_vs_lblcr_get(struct ip_vs_lblcr_table *tbl, __be32 addr) | |||
354 | * IP address to a server. Called under write lock. | 365 | * IP address to a server. Called under write lock. |
355 | */ | 366 | */ |
356 | static inline struct ip_vs_lblcr_entry * | 367 | static inline struct ip_vs_lblcr_entry * |
357 | ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, __be32 daddr, | 368 | ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr, |
358 | struct ip_vs_dest *dest) | 369 | struct ip_vs_dest *dest) |
359 | { | 370 | { |
360 | struct ip_vs_lblcr_entry *en; | 371 | struct ip_vs_lblcr_entry *en; |
361 | 372 | ||
362 | en = ip_vs_lblcr_get(tbl, daddr); | 373 | en = ip_vs_lblcr_get(dest->af, tbl, daddr); |
363 | if (!en) { | 374 | if (!en) { |
364 | en = kmalloc(sizeof(*en), GFP_ATOMIC); | 375 | en = kmalloc(sizeof(*en), GFP_ATOMIC); |
365 | if (!en) { | 376 | if (!en) { |
@@ -367,7 +378,8 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, __be32 daddr, | |||
367 | return NULL; | 378 | return NULL; |
368 | } | 379 | } |
369 | 380 | ||
370 | en->addr = daddr; | 381 | en->af = dest->af; |
382 | ip_vs_addr_copy(dest->af, &en->addr, daddr); | ||
371 | en->lastuse = jiffies; | 383 | en->lastuse = jiffies; |
372 | 384 | ||
373 | /* initilize its dest set */ | 385 | /* initilize its dest set */ |
@@ -544,7 +556,7 @@ static int ip_vs_lblcr_done_svc(struct ip_vs_service *svc) | |||
544 | 556 | ||
545 | 557 | ||
546 | static inline struct ip_vs_dest * | 558 | static inline struct ip_vs_dest * |
547 | __ip_vs_lblcr_schedule(struct ip_vs_service *svc, struct iphdr *iph) | 559 | __ip_vs_lblcr_schedule(struct ip_vs_service *svc) |
548 | { | 560 | { |
549 | struct ip_vs_dest *dest, *least; | 561 | struct ip_vs_dest *dest, *least; |
550 | int loh, doh; | 562 | int loh, doh; |
@@ -596,12 +608,13 @@ __ip_vs_lblcr_schedule(struct ip_vs_service *svc, struct iphdr *iph) | |||
596 | } | 608 | } |
597 | } | 609 | } |
598 | 610 | ||
599 | IP_VS_DBG(6, "LBLCR: server %pI4:%d " | 611 | IP_VS_DBG_BUF(6, "LBLCR: server %s:%d " |
600 | "activeconns %d refcnt %d weight %d overhead %d\n", | 612 | "activeconns %d refcnt %d weight %d overhead %d\n", |
601 | &least->addr.ip, ntohs(least->port), | 613 | IP_VS_DBG_ADDR(least->af, &least->addr), |
602 | atomic_read(&least->activeconns), | 614 | ntohs(least->port), |
603 | atomic_read(&least->refcnt), | 615 | atomic_read(&least->activeconns), |
604 | atomic_read(&least->weight), loh); | 616 | atomic_read(&least->refcnt), |
617 | atomic_read(&least->weight), loh); | ||
605 | 618 | ||
606 | return least; | 619 | return least; |
607 | } | 620 | } |
@@ -635,15 +648,17 @@ static struct ip_vs_dest * | |||
635 | ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | 648 | ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) |
636 | { | 649 | { |
637 | struct ip_vs_lblcr_table *tbl = svc->sched_data; | 650 | struct ip_vs_lblcr_table *tbl = svc->sched_data; |
638 | struct iphdr *iph = ip_hdr(skb); | 651 | struct ip_vs_iphdr iph; |
639 | struct ip_vs_dest *dest = NULL; | 652 | struct ip_vs_dest *dest = NULL; |
640 | struct ip_vs_lblcr_entry *en; | 653 | struct ip_vs_lblcr_entry *en; |
641 | 654 | ||
655 | ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph); | ||
656 | |||
642 | IP_VS_DBG(6, "ip_vs_lblcr_schedule(): Scheduling...\n"); | 657 | IP_VS_DBG(6, "ip_vs_lblcr_schedule(): Scheduling...\n"); |
643 | 658 | ||
644 | /* First look in our cache */ | 659 | /* First look in our cache */ |
645 | read_lock(&svc->sched_lock); | 660 | read_lock(&svc->sched_lock); |
646 | en = ip_vs_lblcr_get(tbl, iph->daddr); | 661 | en = ip_vs_lblcr_get(svc->af, tbl, &iph.daddr); |
647 | if (en) { | 662 | if (en) { |
648 | /* We only hold a read lock, but this is atomic */ | 663 | /* We only hold a read lock, but this is atomic */ |
649 | en->lastuse = jiffies; | 664 | en->lastuse = jiffies; |
@@ -673,7 +688,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | |||
673 | } | 688 | } |
674 | 689 | ||
675 | /* The cache entry is invalid, time to schedule */ | 690 | /* The cache entry is invalid, time to schedule */ |
676 | dest = __ip_vs_lblcr_schedule(svc, iph); | 691 | dest = __ip_vs_lblcr_schedule(svc); |
677 | if (!dest) { | 692 | if (!dest) { |
678 | IP_VS_DBG(1, "no destination available\n"); | 693 | IP_VS_DBG(1, "no destination available\n"); |
679 | read_unlock(&svc->sched_lock); | 694 | read_unlock(&svc->sched_lock); |
@@ -691,7 +706,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | |||
691 | goto out; | 706 | goto out; |
692 | 707 | ||
693 | /* No cache entry, time to schedule */ | 708 | /* No cache entry, time to schedule */ |
694 | dest = __ip_vs_lblcr_schedule(svc, iph); | 709 | dest = __ip_vs_lblcr_schedule(svc); |
695 | if (!dest) { | 710 | if (!dest) { |
696 | IP_VS_DBG(1, "no destination available\n"); | 711 | IP_VS_DBG(1, "no destination available\n"); |
697 | return NULL; | 712 | return NULL; |
@@ -699,12 +714,13 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb) | |||
699 | 714 | ||
700 | /* If we fail to create a cache entry, we'll just use the valid dest */ | 715 | /* If we fail to create a cache entry, we'll just use the valid dest */ |
701 | write_lock(&svc->sched_lock); | 716 | write_lock(&svc->sched_lock); |
702 | ip_vs_lblcr_new(tbl, iph->daddr, dest); | 717 | ip_vs_lblcr_new(tbl, &iph.daddr, dest); |
703 | write_unlock(&svc->sched_lock); | 718 | write_unlock(&svc->sched_lock); |
704 | 719 | ||
705 | out: | 720 | out: |
706 | IP_VS_DBG(6, "LBLCR: destination IP address %pI4 --> server %pI4:%d\n", | 721 | IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n", |
707 | &iph->daddr, &dest->addr.ip, ntohs(dest->port)); | 722 | IP_VS_DBG_ADDR(svc->af, &iph.daddr), |
723 | IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); | ||
708 | 724 | ||
709 | return dest; | 725 | return dest; |
710 | } | 726 | } |
@@ -720,7 +736,7 @@ static struct ip_vs_scheduler ip_vs_lblcr_scheduler = | |||
720 | .module = THIS_MODULE, | 736 | .module = THIS_MODULE, |
721 | .n_list = LIST_HEAD_INIT(ip_vs_lblcr_scheduler.n_list), | 737 | .n_list = LIST_HEAD_INIT(ip_vs_lblcr_scheduler.n_list), |
722 | #ifdef CONFIG_IP_VS_IPV6 | 738 | #ifdef CONFIG_IP_VS_IPV6 |
723 | .supports_ipv6 = 0, | 739 | .supports_ipv6 = 1, |
724 | #endif | 740 | #endif |
725 | .init_service = ip_vs_lblcr_init_svc, | 741 | .init_service = ip_vs_lblcr_init_svc, |
726 | .done_service = ip_vs_lblcr_done_svc, | 742 | .done_service = ip_vs_lblcr_done_svc, |