diff options
author | Julius Volz <juliusv@google.com> | 2008-09-02 09:55:48 -0400 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2008-09-04 21:17:10 -0400 |
commit | 7937df1564783806c285d34a1c6fd63d8da29d7a (patch) | |
tree | 090dbabafffef92aff1e04aa163435c3ce6db4c9 /net/ipv4/ipvs | |
parent | 2a3b791e6e1169f374224d164738e9f7be703d77 (diff) |
IPVS: Convert real server lookup functions
Convert functions for looking up destinations (real servers) to support
IPv6 services/dests.
Signed-off-by: Julius Volz <juliusv@google.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'net/ipv4/ipvs')
-rw-r--r-- | net/ipv4/ipvs/ip_vs_conn.c | 5 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_core.c | 4 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_ctl.c | 80 | ||||
-rw-r--r-- | net/ipv4/ipvs/ip_vs_sync.c | 7 |
4 files changed, 62 insertions, 34 deletions
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index f5dddad6d5e4..c2a42a62433b 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c | |||
@@ -491,8 +491,9 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp) | |||
491 | struct ip_vs_dest *dest; | 491 | struct ip_vs_dest *dest; |
492 | 492 | ||
493 | if ((cp) && (!cp->dest)) { | 493 | if ((cp) && (!cp->dest)) { |
494 | dest = ip_vs_find_dest(cp->daddr.ip, cp->dport, | 494 | dest = ip_vs_find_dest(cp->af, &cp->daddr, cp->dport, |
495 | cp->vaddr.ip, cp->vport, cp->protocol); | 495 | &cp->vaddr, cp->vport, |
496 | cp->protocol); | ||
496 | ip_vs_bind_dest(cp, dest); | 497 | ip_vs_bind_dest(cp, dest); |
497 | return dest; | 498 | return dest; |
498 | } else | 499 | } else |
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 035a511e12f7..27bef1d67aa7 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
@@ -957,8 +957,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, | |||
957 | sizeof(_ports), _ports); | 957 | sizeof(_ports), _ports); |
958 | if (pptr == NULL) | 958 | if (pptr == NULL) |
959 | return NF_ACCEPT; /* Not for me */ | 959 | return NF_ACCEPT; /* Not for me */ |
960 | if (ip_vs_lookup_real_service(iph.protocol, | 960 | if (ip_vs_lookup_real_service(af, iph.protocol, |
961 | iph.saddr.ip, | 961 | &iph.saddr, |
962 | pptr[0])) { | 962 | pptr[0])) { |
963 | /* | 963 | /* |
964 | * Notify the real server: there is no | 964 | * Notify the real server: there is no |
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c index 1f3fc66e6943..bb0e1e3c8857 100644 --- a/net/ipv4/ipvs/ip_vs_ctl.c +++ b/net/ipv4/ipvs/ip_vs_ctl.c | |||
@@ -492,11 +492,20 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest) | |||
492 | /* | 492 | /* |
493 | * Returns hash value for real service | 493 | * Returns hash value for real service |
494 | */ | 494 | */ |
495 | static __inline__ unsigned ip_vs_rs_hashkey(__be32 addr, __be16 port) | 495 | static inline unsigned ip_vs_rs_hashkey(int af, |
496 | const union nf_inet_addr *addr, | ||
497 | __be16 port) | ||
496 | { | 498 | { |
497 | register unsigned porth = ntohs(port); | 499 | register unsigned porth = ntohs(port); |
500 | __be32 addr_fold = addr->ip; | ||
501 | |||
502 | #ifdef CONFIG_IP_VS_IPV6 | ||
503 | if (af == AF_INET6) | ||
504 | addr_fold = addr->ip6[0]^addr->ip6[1]^ | ||
505 | addr->ip6[2]^addr->ip6[3]; | ||
506 | #endif | ||
498 | 507 | ||
499 | return (ntohl(addr)^(porth>>IP_VS_RTAB_BITS)^porth) | 508 | return (ntohl(addr_fold)^(porth>>IP_VS_RTAB_BITS)^porth) |
500 | & IP_VS_RTAB_MASK; | 509 | & IP_VS_RTAB_MASK; |
501 | } | 510 | } |
502 | 511 | ||
@@ -516,7 +525,8 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest) | |||
516 | * Hash by proto,addr,port, | 525 | * Hash by proto,addr,port, |
517 | * which are the parameters of the real service. | 526 | * which are the parameters of the real service. |
518 | */ | 527 | */ |
519 | hash = ip_vs_rs_hashkey(dest->addr.ip, dest->port); | 528 | hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port); |
529 | |||
520 | list_add(&dest->d_list, &ip_vs_rtable[hash]); | 530 | list_add(&dest->d_list, &ip_vs_rtable[hash]); |
521 | 531 | ||
522 | return 1; | 532 | return 1; |
@@ -543,7 +553,9 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest) | |||
543 | * Lookup real service by <proto,addr,port> in the real service table. | 553 | * Lookup real service by <proto,addr,port> in the real service table. |
544 | */ | 554 | */ |
545 | struct ip_vs_dest * | 555 | struct ip_vs_dest * |
546 | ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) | 556 | ip_vs_lookup_real_service(int af, __u16 protocol, |
557 | const union nf_inet_addr *daddr, | ||
558 | __be16 dport) | ||
547 | { | 559 | { |
548 | unsigned hash; | 560 | unsigned hash; |
549 | struct ip_vs_dest *dest; | 561 | struct ip_vs_dest *dest; |
@@ -552,11 +564,12 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) | |||
552 | * Check for "full" addressed entries | 564 | * Check for "full" addressed entries |
553 | * Return the first found entry | 565 | * Return the first found entry |
554 | */ | 566 | */ |
555 | hash = ip_vs_rs_hashkey(daddr, dport); | 567 | hash = ip_vs_rs_hashkey(af, daddr, dport); |
556 | 568 | ||
557 | read_lock(&__ip_vs_rs_lock); | 569 | read_lock(&__ip_vs_rs_lock); |
558 | list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) { | 570 | list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) { |
559 | if ((dest->addr.ip == daddr) | 571 | if ((dest->af == af) |
572 | && ip_vs_addr_equal(af, &dest->addr, daddr) | ||
560 | && (dest->port == dport) | 573 | && (dest->port == dport) |
561 | && ((dest->protocol == protocol) || | 574 | && ((dest->protocol == protocol) || |
562 | dest->vfwmark)) { | 575 | dest->vfwmark)) { |
@@ -574,7 +587,8 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) | |||
574 | * Lookup destination by {addr,port} in the given service | 587 | * Lookup destination by {addr,port} in the given service |
575 | */ | 588 | */ |
576 | static struct ip_vs_dest * | 589 | static struct ip_vs_dest * |
577 | ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) | 590 | ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, |
591 | __be16 dport) | ||
578 | { | 592 | { |
579 | struct ip_vs_dest *dest; | 593 | struct ip_vs_dest *dest; |
580 | 594 | ||
@@ -582,7 +596,9 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) | |||
582 | * Find the destination for the given service | 596 | * Find the destination for the given service |
583 | */ | 597 | */ |
584 | list_for_each_entry(dest, &svc->destinations, n_list) { | 598 | list_for_each_entry(dest, &svc->destinations, n_list) { |
585 | if ((dest->addr.ip == daddr) && (dest->port == dport)) { | 599 | if ((dest->af == svc->af) |
600 | && ip_vs_addr_equal(svc->af, &dest->addr, daddr) | ||
601 | && (dest->port == dport)) { | ||
586 | /* HIT */ | 602 | /* HIT */ |
587 | return dest; | 603 | return dest; |
588 | } | 604 | } |
@@ -601,14 +617,15 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) | |||
601 | * ip_vs_lookup_real_service() looked promissing, but | 617 | * ip_vs_lookup_real_service() looked promissing, but |
602 | * seems not working as expected. | 618 | * seems not working as expected. |
603 | */ | 619 | */ |
604 | struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, | 620 | struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr, |
605 | __be32 vaddr, __be16 vport, __u16 protocol) | 621 | __be16 dport, |
622 | const union nf_inet_addr *vaddr, | ||
623 | __be16 vport, __u16 protocol) | ||
606 | { | 624 | { |
607 | struct ip_vs_dest *dest; | 625 | struct ip_vs_dest *dest; |
608 | struct ip_vs_service *svc; | 626 | struct ip_vs_service *svc; |
609 | union nf_inet_addr _vaddr = { .ip = vaddr }; | ||
610 | 627 | ||
611 | svc = ip_vs_service_get(AF_INET, 0, protocol, &_vaddr, vport); | 628 | svc = ip_vs_service_get(af, 0, protocol, vaddr, vport); |
612 | if (!svc) | 629 | if (!svc) |
613 | return NULL; | 630 | return NULL; |
614 | dest = ip_vs_lookup_dest(svc, daddr, dport); | 631 | dest = ip_vs_lookup_dest(svc, daddr, dport); |
@@ -629,7 +646,8 @@ struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, | |||
629 | * scheduling. | 646 | * scheduling. |
630 | */ | 647 | */ |
631 | static struct ip_vs_dest * | 648 | static struct ip_vs_dest * |
632 | ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) | 649 | ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, |
650 | __be16 dport) | ||
633 | { | 651 | { |
634 | struct ip_vs_dest *dest, *nxt; | 652 | struct ip_vs_dest *dest, *nxt; |
635 | 653 | ||
@@ -637,17 +655,19 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) | |||
637 | * Find the destination in trash | 655 | * Find the destination in trash |
638 | */ | 656 | */ |
639 | list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) { | 657 | list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) { |
640 | IP_VS_DBG(3, "Destination %u/%u.%u.%u.%u:%u still in trash, " | 658 | IP_VS_DBG_BUF(3, "Destination %u/%s:%u still in trash, " |
641 | "dest->refcnt=%d\n", | 659 | "dest->refcnt=%d\n", |
642 | dest->vfwmark, | 660 | dest->vfwmark, |
643 | NIPQUAD(dest->addr.ip), ntohs(dest->port), | 661 | IP_VS_DBG_ADDR(svc->af, &dest->addr), |
644 | atomic_read(&dest->refcnt)); | 662 | ntohs(dest->port), |
645 | if (dest->addr.ip == daddr && | 663 | atomic_read(&dest->refcnt)); |
664 | if (dest->af == svc->af && | ||
665 | ip_vs_addr_equal(svc->af, &dest->addr, daddr) && | ||
646 | dest->port == dport && | 666 | dest->port == dport && |
647 | dest->vfwmark == svc->fwmark && | 667 | dest->vfwmark == svc->fwmark && |
648 | dest->protocol == svc->protocol && | 668 | dest->protocol == svc->protocol && |
649 | (svc->fwmark || | 669 | (svc->fwmark || |
650 | (dest->vaddr.ip == svc->addr.ip && | 670 | (ip_vs_addr_equal(svc->af, &dest->vaddr, &svc->addr) && |
651 | dest->vport == svc->port))) { | 671 | dest->vport == svc->port))) { |
652 | /* HIT */ | 672 | /* HIT */ |
653 | return dest; | 673 | return dest; |
@@ -657,10 +677,11 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) | |||
657 | * Try to purge the destination from trash if not referenced | 677 | * Try to purge the destination from trash if not referenced |
658 | */ | 678 | */ |
659 | if (atomic_read(&dest->refcnt) == 1) { | 679 | if (atomic_read(&dest->refcnt) == 1) { |
660 | IP_VS_DBG(3, "Removing destination %u/%u.%u.%u.%u:%u " | 680 | IP_VS_DBG_BUF(3, "Removing destination %u/%s:%u " |
661 | "from trash\n", | 681 | "from trash\n", |
662 | dest->vfwmark, | 682 | dest->vfwmark, |
663 | NIPQUAD(dest->addr.ip), ntohs(dest->port)); | 683 | IP_VS_DBG_ADDR(svc->af, &dest->addr), |
684 | ntohs(dest->port)); | ||
664 | list_del(&dest->n_list); | 685 | list_del(&dest->n_list); |
665 | ip_vs_dst_reset(dest); | 686 | ip_vs_dst_reset(dest); |
666 | __ip_vs_unbind_svc(dest); | 687 | __ip_vs_unbind_svc(dest); |
@@ -847,7 +868,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) | |||
847 | /* | 868 | /* |
848 | * Check if the dest already exists in the list | 869 | * Check if the dest already exists in the list |
849 | */ | 870 | */ |
850 | dest = ip_vs_lookup_dest(svc, daddr.ip, dport); | 871 | dest = ip_vs_lookup_dest(svc, &daddr, dport); |
872 | |||
851 | if (dest != NULL) { | 873 | if (dest != NULL) { |
852 | IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n"); | 874 | IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n"); |
853 | return -EEXIST; | 875 | return -EEXIST; |
@@ -857,7 +879,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) | |||
857 | * Check if the dest already exists in the trash and | 879 | * Check if the dest already exists in the trash and |
858 | * is from the same service | 880 | * is from the same service |
859 | */ | 881 | */ |
860 | dest = ip_vs_trash_get_dest(svc, daddr.ip, dport); | 882 | dest = ip_vs_trash_get_dest(svc, &daddr, dport); |
883 | |||
861 | if (dest != NULL) { | 884 | if (dest != NULL) { |
862 | IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, " | 885 | IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, " |
863 | "dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n", | 886 | "dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n", |
@@ -956,7 +979,8 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) | |||
956 | /* | 979 | /* |
957 | * Lookup the destination list | 980 | * Lookup the destination list |
958 | */ | 981 | */ |
959 | dest = ip_vs_lookup_dest(svc, daddr.ip, dport); | 982 | dest = ip_vs_lookup_dest(svc, &daddr, dport); |
983 | |||
960 | if (dest == NULL) { | 984 | if (dest == NULL) { |
961 | IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n"); | 985 | IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n"); |
962 | return -ENOENT; | 986 | return -ENOENT; |
@@ -1054,7 +1078,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) | |||
1054 | 1078 | ||
1055 | EnterFunction(2); | 1079 | EnterFunction(2); |
1056 | 1080 | ||
1057 | dest = ip_vs_lookup_dest(svc, udest->addr.ip, dport); | 1081 | dest = ip_vs_lookup_dest(svc, &udest->addr, dport); |
1058 | 1082 | ||
1059 | if (dest == NULL) { | 1083 | if (dest == NULL) { |
1060 | IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n"); | 1084 | IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n"); |
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 3ce1093e0670..40647edf1024 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c | |||
@@ -383,8 +383,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) | |||
383 | * If it is not found the connection will remain unbound | 383 | * If it is not found the connection will remain unbound |
384 | * but still handled. | 384 | * but still handled. |
385 | */ | 385 | */ |
386 | dest = ip_vs_find_dest(s->daddr, s->dport, | 386 | dest = ip_vs_find_dest(AF_INET, |
387 | s->vaddr, s->vport, | 387 | (union nf_inet_addr *)&s->daddr, |
388 | s->dport, | ||
389 | (union nf_inet_addr *)&s->vaddr, | ||
390 | s->vport, | ||
388 | s->protocol); | 391 | s->protocol); |
389 | /* Set the approprite ativity flag */ | 392 | /* Set the approprite ativity flag */ |
390 | if (s->protocol == IPPROTO_TCP) { | 393 | if (s->protocol == IPPROTO_TCP) { |