Commit 7937df15 authored by Julius Volz's avatar Julius Volz Committed by Simon Horman

IPVS: Convert real server lookup functions

Convert functions for looking up destinations (real servers) to support
IPv6 services/dests.
Signed-off-by: default avatarJulius Volz <juliusv@google.com>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent 2a3b791e
...@@ -804,14 +804,16 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc) ...@@ -804,14 +804,16 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc)
} }
extern struct ip_vs_dest * 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 int ip_vs_use_count_inc(void);
extern void ip_vs_use_count_dec(void); extern void ip_vs_use_count_dec(void);
extern int ip_vs_control_init(void); extern int ip_vs_control_init(void);
extern void ip_vs_control_cleanup(void); extern void ip_vs_control_cleanup(void);
extern struct ip_vs_dest * extern struct ip_vs_dest *
ip_vs_find_dest(__be32 daddr, __be16 dport, ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport,
__be32 vaddr, __be16 vport, __u16 protocol); 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); extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
......
...@@ -491,8 +491,9 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp) ...@@ -491,8 +491,9 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp)
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
if ((cp) && (!cp->dest)) { if ((cp) && (!cp->dest)) {
dest = ip_vs_find_dest(cp->daddr.ip, cp->dport, dest = ip_vs_find_dest(cp->af, &cp->daddr, cp->dport,
cp->vaddr.ip, cp->vport, cp->protocol); &cp->vaddr, cp->vport,
cp->protocol);
ip_vs_bind_dest(cp, dest); ip_vs_bind_dest(cp, dest);
return dest; return dest;
} else } else
......
...@@ -957,8 +957,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, ...@@ -957,8 +957,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb,
sizeof(_ports), _ports); sizeof(_ports), _ports);
if (pptr == NULL) if (pptr == NULL)
return NF_ACCEPT; /* Not for me */ return NF_ACCEPT; /* Not for me */
if (ip_vs_lookup_real_service(iph.protocol, if (ip_vs_lookup_real_service(af, iph.protocol,
iph.saddr.ip, &iph.saddr,
pptr[0])) { pptr[0])) {
/* /*
* Notify the real server: there is no * Notify the real server: there is no
......
...@@ -492,11 +492,20 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest) ...@@ -492,11 +492,20 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest)
/* /*
* Returns hash value for real service * 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); 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; & IP_VS_RTAB_MASK;
} }
...@@ -516,7 +525,8 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest) ...@@ -516,7 +525,8 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest)
* Hash by proto,addr,port, * Hash by proto,addr,port,
* which are the parameters of the real service. * 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]); list_add(&dest->d_list, &ip_vs_rtable[hash]);
return 1; return 1;
...@@ -543,7 +553,9 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest) ...@@ -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. * Lookup real service by <proto,addr,port> in the real service table.
*/ */
struct ip_vs_dest * 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; unsigned hash;
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
...@@ -552,11 +564,12 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) ...@@ -552,11 +564,12 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport)
* Check for "full" addressed entries * Check for "full" addressed entries
* Return the first found entry * 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); read_lock(&__ip_vs_rs_lock);
list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) { 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->port == dport)
&& ((dest->protocol == protocol) || && ((dest->protocol == protocol) ||
dest->vfwmark)) { dest->vfwmark)) {
...@@ -574,7 +587,8 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport) ...@@ -574,7 +587,8 @@ ip_vs_lookup_real_service(__u16 protocol, __be32 daddr, __be16 dport)
* Lookup destination by {addr,port} in the given service * Lookup destination by {addr,port} in the given service
*/ */
static struct ip_vs_dest * 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; struct ip_vs_dest *dest;
...@@ -582,7 +596,9 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) ...@@ -582,7 +596,9 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
* Find the destination for the given service * Find the destination for the given service
*/ */
list_for_each_entry(dest, &svc->destinations, n_list) { 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 */ /* HIT */
return dest; return dest;
} }
...@@ -601,14 +617,15 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) ...@@ -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 * ip_vs_lookup_real_service() looked promissing, but
* seems not working as expected. * seems not working as expected.
*/ */
struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport, struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr,
__be32 vaddr, __be16 vport, __u16 protocol) __be16 dport,
const union nf_inet_addr *vaddr,
__be16 vport, __u16 protocol)
{ {
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
struct ip_vs_service *svc; 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) if (!svc)
return NULL; return NULL;
dest = ip_vs_lookup_dest(svc, daddr, dport); 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,7 +646,8 @@ struct ip_vs_dest *ip_vs_find_dest(__be32 daddr, __be16 dport,
* scheduling. * scheduling.
*/ */
static struct ip_vs_dest * 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; struct ip_vs_dest *dest, *nxt;
...@@ -637,17 +655,19 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) ...@@ -637,17 +655,19 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport)
* Find the destination in trash * Find the destination in trash
*/ */
list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) { 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->refcnt=%d\n",
dest->vfwmark, dest->vfwmark,
NIPQUAD(dest->addr.ip), ntohs(dest->port), IP_VS_DBG_ADDR(svc->af, &dest->addr),
ntohs(dest->port),
atomic_read(&dest->refcnt)); 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->port == dport &&
dest->vfwmark == svc->fwmark && dest->vfwmark == svc->fwmark &&
dest->protocol == svc->protocol && dest->protocol == svc->protocol &&
(svc->fwmark || (svc->fwmark ||
(dest->vaddr.ip == svc->addr.ip && (ip_vs_addr_equal(svc->af, &dest->vaddr, &svc->addr) &&
dest->vport == svc->port))) { dest->vport == svc->port))) {
/* HIT */ /* HIT */
return dest; return dest;
...@@ -657,10 +677,11 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __be32 daddr, __be16 dport) ...@@ -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 * Try to purge the destination from trash if not referenced
*/ */
if (atomic_read(&dest->refcnt) == 1) { 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", "from trash\n",
dest->vfwmark, 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); list_del(&dest->n_list);
ip_vs_dst_reset(dest); ip_vs_dst_reset(dest);
__ip_vs_unbind_svc(dest); __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,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 * 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) { if (dest != NULL) {
IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n"); IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n");
return -EEXIST; return -EEXIST;
...@@ -857,7 +879,8 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) ...@@ -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 * Check if the dest already exists in the trash and
* is from the same service * 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) { if (dest != NULL) {
IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, " IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, "
"dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n", "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,7 +979,8 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
/* /*
* Lookup the destination list * Lookup the destination list
*/ */
dest = ip_vs_lookup_dest(svc, daddr.ip, dport); dest = ip_vs_lookup_dest(svc, &daddr, dport);
if (dest == NULL) { if (dest == NULL) {
IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n"); IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n");
return -ENOENT; return -ENOENT;
...@@ -1054,7 +1078,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest) ...@@ -1054,7 +1078,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
EnterFunction(2); EnterFunction(2);
dest = ip_vs_lookup_dest(svc, udest->addr.ip, dport); dest = ip_vs_lookup_dest(svc, &udest->addr, dport);
if (dest == NULL) { if (dest == NULL) {
IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n"); IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n");
......
...@@ -383,8 +383,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) ...@@ -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 * If it is not found the connection will remain unbound
* but still handled. * but still handled.
*/ */
dest = ip_vs_find_dest(s->daddr, s->dport, dest = ip_vs_find_dest(AF_INET,
s->vaddr, s->vport, (union nf_inet_addr *)&s->daddr,
s->dport,
(union nf_inet_addr *)&s->vaddr,
s->vport,
s->protocol); s->protocol);
/* Set the approprite ativity flag */ /* Set the approprite ativity flag */
if (s->protocol == IPPROTO_TCP) { if (s->protocol == IPPROTO_TCP) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment