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>
This commit is contained in:
committed by
Simon Horman
parent
2a3b791e6e
commit
7937df1564
@@ -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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
* 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)
|
|||||||
* 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)
|
|||||||
* 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)
|
|||||||
* 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)
|
|||||||
* 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)
|
|||||||
* 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,
|
|||||||
* 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)
|
|||||||
* 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),
|
||||||
atomic_read(&dest->refcnt));
|
ntohs(dest->port),
|
||||||
if (dest->addr.ip == daddr &&
|
atomic_read(&dest->refcnt));
|
||||||
|
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)
|
|||||||
* 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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
* 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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
* 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) {
|
||||||
|
Reference in New Issue
Block a user