mirror of
https://github.com/adulau/aha.git
synced 2025-01-01 13:46:24 +00:00
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:
parent
2a3b791e6e
commit
7937df1564
5 changed files with 67 additions and 37 deletions
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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, "
|
||||
"dest->refcnt=%d\n",
|
||||
dest->vfwmark,
|
||||
NIPQUAD(dest->addr.ip), ntohs(dest->port),
|
||||
atomic_read(&dest->refcnt));
|
||||
if (dest->addr.ip == daddr &&
|
||||
IP_VS_DBG_BUF(3, "Destination %u/%s:%u still in trash, "
|
||||
"dest->refcnt=%d\n",
|
||||
dest->vfwmark,
|
||||
IP_VS_DBG_ADDR(svc->af, &dest->addr),
|
||||
ntohs(dest->port),
|
||||
atomic_read(&dest->refcnt));
|
||||
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;
|
||||
|
@ -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 "
|
||||
"from trash\n",
|
||||
dest->vfwmark,
|
||||
NIPQUAD(dest->addr.ip), ntohs(dest->port));
|
||||
IP_VS_DBG_BUF(3, "Removing destination %u/%s:%u "
|
||||
"from trash\n",
|
||||
dest->vfwmark,
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
|
|
@ -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…
Reference in a new issue