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 | |
| 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>
| -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, |
