Loading include/net/ip_vs.h +5 −3 Original line number Diff line number Diff line Loading @@ -804,14 +804,16 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc) } extern struct ip_vs_dest * ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport); ip_vs_lookup_real_service(int af, __u16 protocol, const union nf_inet_addr *daddr, __be16 dport); extern int ip_vs_use_count_inc(void); extern void ip_vs_use_count_dec(void); extern int ip_vs_control_init(void); extern void ip_vs_control_cleanup(void); extern struct ip_vs_dest * ip_vs_find_dest(__be32 daddr, __be16 dport, __be32 vaddr, __be16 vport, __u16 protocol); ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport, const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol); extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); Loading net/ipv4/ipvs/ip_vs_conn.c +3 −2 Original line number Diff line number Diff line Loading @@ -491,8 +491,9 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp) struct ip_vs_dest *dest; if ((cp) && (!cp->dest)) { dest = ip_vs_find_dest(cp->daddr.ip, cp->dport, cp->vaddr.ip, cp->vport, cp->protocol); dest = ip_vs_find_dest(cp->af, &cp->daddr, cp->dport, &cp->vaddr, cp->vport, cp->protocol); ip_vs_bind_dest(cp, dest); return dest; } else Loading net/ipv4/ipvs/ip_vs_core.c +2 −2 Original line number Diff line number Diff line Loading @@ -957,8 +957,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, sizeof(_ports), _ports); if (pptr == NULL) return NF_ACCEPT; /* Not for me */ if (ip_vs_lookup_real_service(iph.protocol, iph.saddr.ip, if (ip_vs_lookup_real_service(af, iph.protocol, &iph.saddr, pptr[0])) { /* * Notify the real server: there is no Loading net/ipv4/ipvs/ip_vs_ctl.c +52 −28 Original line number Diff line number Diff line Loading @@ -492,11 +492,20 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest) /* * Returns hash value for real service */ static __inline__ unsigned ip_vs_rs_hashkey(__be32 addr, __be16 port) static inline unsigned ip_vs_rs_hashkey(int af, const union nf_inet_addr *addr, __be16 port) { register unsigned porth = ntohs(port); __be32 addr_fold = addr->ip; return (ntohl(addr)^(porth>>IP_VS_RTAB_BITS)^porth) #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) addr_fold = addr->ip6[0]^addr->ip6[1]^ addr->ip6[2]^addr->ip6[3]; #endif return (ntohl(addr_fold)^(porth>>IP_VS_RTAB_BITS)^porth) & IP_VS_RTAB_MASK; } Loading @@ -516,7 +525,8 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest) * Hash by proto,addr,port, * which are the parameters of the real service. */ hash = ip_vs_rs_hashkey(dest->addr.ip, dest->port); hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port); list_add(&dest->d_list, &ip_vs_rtable[hash]); return 1; Loading @@ -543,7 +553,9 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest) * Lookup real service by <proto,addr,port> in the real service table. */ struct ip_vs_dest * ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) ip_vs_lookup_real_service(int af, __u16 protocol, const union nf_inet_addr *daddr, __be16 dport) { unsigned hash; struct ip_vs_dest *dest; Loading @@ -552,11 +564,12 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) * Check for "full" addressed entries * Return the first found entry */ hash = ip_vs_rs_hashkey(daddr, dport); hash = ip_vs_rs_hashkey(af, daddr, dport); read_lock(&__ip_vs_rs_lock); list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) { if ((dest->addr.ip == daddr) if ((dest->af == af) && ip_vs_addr_equal(af, &dest->addr, daddr) && (dest->port == dport) && ((dest->protocol == protocol) || dest->vfwmark)) { Loading @@ -574,7 +587,8 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) * Lookup destination by {addr,port} in the given service */ static struct ip_vs_dest * ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, __be16 dport) { struct ip_vs_dest *dest; Loading @@ -582,7 +596,9 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) * Find the destination for the given service */ list_for_each_entry(dest, &svc->destinations, n_list) { if ((dest->addr.ip == daddr) && (dest->port == dport)) { if ((dest->af == svc->af) && ip_vs_addr_equal(svc->af, &dest->addr, daddr) && (dest->port == dport)) { /* HIT */ return dest; } Loading @@ -601,14 +617,15 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) * ip_vs_lookup_real_service() looked promissing, but * seems not working as expected. */ struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, __be32 vaddr, __be16 vport, __u16 protocol) struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport, const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol) { struct ip_vs_dest *dest; struct ip_vs_service *svc; union nf_inet_addr _vaddr = { .ip = vaddr }; svc = ip_vs_service_get(AF_INET, 0, protocol, &_vaddr, vport); svc = ip_vs_service_get(af, 0, protocol, vaddr, vport); if (!svc) return NULL; dest = ip_vs_lookup_dest(svc, daddr, dport); Loading @@ -629,7 +646,8 @@ struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, * scheduling. */ static struct ip_vs_dest * ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, __be16 dport) { struct ip_vs_dest *dest, *nxt; Loading @@ -637,17 +655,19 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) * Find the destination in trash */ list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) { IP_VS_DBG(3, "Destination %u/%u.%u.%u.%u:%u still in trash, " IP_VS_DBG_BUF(3, "Destination %u/%s:%u still in trash, " "dest->refcnt=%d\n", dest->vfwmark, NIPQUAD(dest->addr.ip), ntohs(dest->port), IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port), atomic_read(&dest->refcnt)); if (dest->addr.ip == daddr && if (dest->af == svc->af && ip_vs_addr_equal(svc->af, &dest->addr, daddr) && dest->port == dport && dest->vfwmark == svc->fwmark && dest->protocol == svc->protocol && (svc->fwmark || (dest->vaddr.ip == svc->addr.ip && (ip_vs_addr_equal(svc->af, &dest->vaddr, &svc->addr) && dest->vport == svc->port))) { /* HIT */ return dest; Loading @@ -657,10 +677,11 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) * Try to purge the destination from trash if not referenced */ if (atomic_read(&dest->refcnt) == 1) { IP_VS_DBG(3, "Removing destination %u/%u.%u.%u.%u:%u " IP_VS_DBG_BUF(3, "Removing destination %u/%s:%u " "from trash\n", dest->vfwmark, NIPQUAD(dest->addr.ip), ntohs(dest->port)); IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); list_del(&dest->n_list); ip_vs_dst_reset(dest); __ip_vs_unbind_svc(dest); Loading Loading @@ -847,7 +868,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) /* * Check if the dest already exists in the list */ dest = ip_vs_lookup_dest(svc, daddr.ip, dport); dest = ip_vs_lookup_dest(svc, &daddr, dport); if (dest != NULL) { IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n"); return -EEXIST; Loading @@ -857,7 +879,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) * Check if the dest already exists in the trash and * is from the same service */ dest = ip_vs_trash_get_dest(svc, daddr.ip, dport); dest = ip_vs_trash_get_dest(svc, &daddr, dport); if (dest != NULL) { IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, " "dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n", Loading Loading @@ -956,7 +979,8 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) /* * Lookup the destination list */ dest = ip_vs_lookup_dest(svc, daddr.ip, dport); dest = ip_vs_lookup_dest(svc, &daddr, dport); if (dest == NULL) { IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n"); return -ENOENT; Loading Loading @@ -1054,7 +1078,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) EnterFunction(2); dest = ip_vs_lookup_dest(svc, udest->addr.ip, dport); dest = ip_vs_lookup_dest(svc, &udest->addr, dport); if (dest == NULL) { IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n"); Loading net/ipv4/ipvs/ip_vs_sync.c +5 −2 Original line number Diff line number Diff line Loading @@ -383,8 +383,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) * If it is not found the connection will remain unbound * but still handled. */ dest = ip_vs_find_dest(s->daddr, s->dport, s->vaddr, s->vport, dest = ip_vs_find_dest(AF_INET, (union nf_inet_addr *)&s->daddr, s->dport, (union nf_inet_addr *)&s->vaddr, s->vport, s->protocol); /* Set the approprite ativity flag */ if (s->protocol == IPPROTO_TCP) { Loading Loading
include/net/ip_vs.h +5 −3 Original line number Diff line number Diff line Loading @@ -804,14 +804,16 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc) } extern struct ip_vs_dest * ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport); ip_vs_lookup_real_service(int af, __u16 protocol, const union nf_inet_addr *daddr, __be16 dport); extern int ip_vs_use_count_inc(void); extern void ip_vs_use_count_dec(void); extern int ip_vs_control_init(void); extern void ip_vs_control_cleanup(void); extern struct ip_vs_dest * ip_vs_find_dest(__be32 daddr, __be16 dport, __be32 vaddr, __be16 vport, __u16 protocol); ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport, const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol); extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); Loading
net/ipv4/ipvs/ip_vs_conn.c +3 −2 Original line number Diff line number Diff line Loading @@ -491,8 +491,9 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp) struct ip_vs_dest *dest; if ((cp) && (!cp->dest)) { dest = ip_vs_find_dest(cp->daddr.ip, cp->dport, cp->vaddr.ip, cp->vport, cp->protocol); dest = ip_vs_find_dest(cp->af, &cp->daddr, cp->dport, &cp->vaddr, cp->vport, cp->protocol); ip_vs_bind_dest(cp, dest); return dest; } else Loading
net/ipv4/ipvs/ip_vs_core.c +2 −2 Original line number Diff line number Diff line Loading @@ -957,8 +957,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, sizeof(_ports), _ports); if (pptr == NULL) return NF_ACCEPT; /* Not for me */ if (ip_vs_lookup_real_service(iph.protocol, iph.saddr.ip, if (ip_vs_lookup_real_service(af, iph.protocol, &iph.saddr, pptr[0])) { /* * Notify the real server: there is no Loading
net/ipv4/ipvs/ip_vs_ctl.c +52 −28 Original line number Diff line number Diff line Loading @@ -492,11 +492,20 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest) /* * Returns hash value for real service */ static __inline__ unsigned ip_vs_rs_hashkey(__be32 addr, __be16 port) static inline unsigned ip_vs_rs_hashkey(int af, const union nf_inet_addr *addr, __be16 port) { register unsigned porth = ntohs(port); __be32 addr_fold = addr->ip; return (ntohl(addr)^(porth>>IP_VS_RTAB_BITS)^porth) #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) addr_fold = addr->ip6[0]^addr->ip6[1]^ addr->ip6[2]^addr->ip6[3]; #endif return (ntohl(addr_fold)^(porth>>IP_VS_RTAB_BITS)^porth) & IP_VS_RTAB_MASK; } Loading @@ -516,7 +525,8 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest) * Hash by proto,addr,port, * which are the parameters of the real service. */ hash = ip_vs_rs_hashkey(dest->addr.ip, dest->port); hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port); list_add(&dest->d_list, &ip_vs_rtable[hash]); return 1; Loading @@ -543,7 +553,9 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest) * Lookup real service by <proto,addr,port> in the real service table. */ struct ip_vs_dest * ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) ip_vs_lookup_real_service(int af, __u16 protocol, const union nf_inet_addr *daddr, __be16 dport) { unsigned hash; struct ip_vs_dest *dest; Loading @@ -552,11 +564,12 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) * Check for "full" addressed entries * Return the first found entry */ hash = ip_vs_rs_hashkey(daddr, dport); hash = ip_vs_rs_hashkey(af, daddr, dport); read_lock(&__ip_vs_rs_lock); list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) { if ((dest->addr.ip == daddr) if ((dest->af == af) && ip_vs_addr_equal(af, &dest->addr, daddr) && (dest->port == dport) && ((dest->protocol == protocol) || dest->vfwmark)) { Loading @@ -574,7 +587,8 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) * Lookup destination by {addr,port} in the given service */ static struct ip_vs_dest * ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, __be16 dport) { struct ip_vs_dest *dest; Loading @@ -582,7 +596,9 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) * Find the destination for the given service */ list_for_each_entry(dest, &svc->destinations, n_list) { if ((dest->addr.ip == daddr) && (dest->port == dport)) { if ((dest->af == svc->af) && ip_vs_addr_equal(svc->af, &dest->addr, daddr) && (dest->port == dport)) { /* HIT */ return dest; } Loading @@ -601,14 +617,15 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) * ip_vs_lookup_real_service() looked promissing, but * seems not working as expected. */ struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, __be32 vaddr, __be16 vport, __u16 protocol) struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport, const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol) { struct ip_vs_dest *dest; struct ip_vs_service *svc; union nf_inet_addr _vaddr = { .ip = vaddr }; svc = ip_vs_service_get(AF_INET, 0, protocol, &_vaddr, vport); svc = ip_vs_service_get(af, 0, protocol, vaddr, vport); if (!svc) return NULL; dest = ip_vs_lookup_dest(svc, daddr, dport); Loading @@ -629,7 +646,8 @@ struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, * scheduling. */ static struct ip_vs_dest * ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, __be16 dport) { struct ip_vs_dest *dest, *nxt; Loading @@ -637,17 +655,19 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) * Find the destination in trash */ list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) { IP_VS_DBG(3, "Destination %u/%u.%u.%u.%u:%u still in trash, " IP_VS_DBG_BUF(3, "Destination %u/%s:%u still in trash, " "dest->refcnt=%d\n", dest->vfwmark, NIPQUAD(dest->addr.ip), ntohs(dest->port), IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port), atomic_read(&dest->refcnt)); if (dest->addr.ip == daddr && if (dest->af == svc->af && ip_vs_addr_equal(svc->af, &dest->addr, daddr) && dest->port == dport && dest->vfwmark == svc->fwmark && dest->protocol == svc->protocol && (svc->fwmark || (dest->vaddr.ip == svc->addr.ip && (ip_vs_addr_equal(svc->af, &dest->vaddr, &svc->addr) && dest->vport == svc->port))) { /* HIT */ return dest; Loading @@ -657,10 +677,11 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) * Try to purge the destination from trash if not referenced */ if (atomic_read(&dest->refcnt) == 1) { IP_VS_DBG(3, "Removing destination %u/%u.%u.%u.%u:%u " IP_VS_DBG_BUF(3, "Removing destination %u/%s:%u " "from trash\n", dest->vfwmark, NIPQUAD(dest->addr.ip), ntohs(dest->port)); IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); list_del(&dest->n_list); ip_vs_dst_reset(dest); __ip_vs_unbind_svc(dest); Loading Loading @@ -847,7 +868,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) /* * Check if the dest already exists in the list */ dest = ip_vs_lookup_dest(svc, daddr.ip, dport); dest = ip_vs_lookup_dest(svc, &daddr, dport); if (dest != NULL) { IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n"); return -EEXIST; Loading @@ -857,7 +879,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) * Check if the dest already exists in the trash and * is from the same service */ dest = ip_vs_trash_get_dest(svc, daddr.ip, dport); dest = ip_vs_trash_get_dest(svc, &daddr, dport); if (dest != NULL) { IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, " "dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n", Loading Loading @@ -956,7 +979,8 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) /* * Lookup the destination list */ dest = ip_vs_lookup_dest(svc, daddr.ip, dport); dest = ip_vs_lookup_dest(svc, &daddr, dport); if (dest == NULL) { IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n"); return -ENOENT; Loading Loading @@ -1054,7 +1078,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) EnterFunction(2); dest = ip_vs_lookup_dest(svc, udest->addr.ip, dport); dest = ip_vs_lookup_dest(svc, &udest->addr, dport); if (dest == NULL) { IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n"); Loading
net/ipv4/ipvs/ip_vs_sync.c +5 −2 Original line number Diff line number Diff line Loading @@ -383,8 +383,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) * If it is not found the connection will remain unbound * but still handled. */ dest = ip_vs_find_dest(s->daddr, s->dport, s->vaddr, s->vport, dest = ip_vs_find_dest(AF_INET, (union nf_inet_addr *)&s->daddr, s->dport, (union nf_inet_addr *)&s->vaddr, s->vport, s->protocol); /* Set the approprite ativity flag */ if (s->protocol == IPPROTO_TCP) { Loading