aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/ip_vs.h8
-rw-r--r--net/ipv4/ipvs/ip_vs_conn.c5
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c80
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c7
5 files changed, 67 insertions, 37 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index ac709fa5a79b..a719c0ef99ec 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -804,14 +804,16 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc)
804} 804}
805 805
806extern struct ip_vs_dest * 806extern struct ip_vs_dest *
807ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport); 807ip_vs_lookup_real_service(int af, __u16 protocol,
808 const union nf_inet_addr *daddr, __be16 dport);
809
808extern int ip_vs_use_count_inc(void); 810extern int ip_vs_use_count_inc(void);
809extern void ip_vs_use_count_dec(void); 811extern void ip_vs_use_count_dec(void);
810extern int ip_vs_control_init(void); 812extern int ip_vs_control_init(void);
811extern void ip_vs_control_cleanup(void); 813extern void ip_vs_control_cleanup(void);
812extern struct ip_vs_dest * 814extern struct ip_vs_dest *
813ip_vs_find_dest(__be32 daddr, __be16 dport, 815ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport,
814 __be32 vaddr, __be16 vport, __u16 protocol); 816 const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol);
815extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); 817extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
816 818
817 819
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 */
495static __inline__ unsigned ip_vs_rs_hashkey(__be32 addr, __be16 port) 495static 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 */
545struct ip_vs_dest * 555struct ip_vs_dest *
546ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) 556ip_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 */
576static struct ip_vs_dest * 589static struct ip_vs_dest *
577ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) 590ip_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 */
604struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, 620struct 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 */
631static struct ip_vs_dest * 648static struct ip_vs_dest *
632ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) 649ip_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) {