Skip to content

Commit

Permalink
IPVS: Extend functions for getting/creating connections
Browse files Browse the repository at this point in the history
Extend functions for getting/creating connections and connection
templates for IPv6 support and fix the callers.

Signed-off-by: Julius Volz <juliusv@google.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
  • Loading branch information
Julius Volz authored and Simon Horman committed Sep 5, 2008
1 parent 0bbdd42 commit 28364a5
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 163 deletions.
16 changes: 11 additions & 5 deletions include/net/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -642,11 +642,16 @@ enum {
};

extern struct ip_vs_conn *ip_vs_conn_in_get
(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port);

extern struct ip_vs_conn *ip_vs_ct_in_get
(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port);

extern struct ip_vs_conn *ip_vs_conn_out_get
(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port);
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port);

/* put back the conn without restarting its timer */
static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
Expand All @@ -657,8 +662,9 @@ extern void ip_vs_conn_put(struct ip_vs_conn *cp);
extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);

extern struct ip_vs_conn *
ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport,
__be32 daddr, __be16 dport, unsigned flags,
ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
const union nf_inet_addr *vaddr, __be16 vport,
const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
struct ip_vs_dest *dest);
extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);

Expand Down
100 changes: 61 additions & 39 deletions net/ipv4/ipvs/ip_vs_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,18 @@ static inline void ct_write_unlock_bh(unsigned key)
/*
* Returns hash value for IPVS connection entry
*/
static unsigned int ip_vs_conn_hashkey(unsigned proto, __be32 addr, __be16 port)
static unsigned int ip_vs_conn_hashkey(int af, unsigned proto,
const union nf_inet_addr *addr,
__be16 port)
{
return jhash_3words((__force u32)addr, (__force u32)port, proto, ip_vs_conn_rnd)
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
return jhash_3words(jhash(addr, 16, ip_vs_conn_rnd),
(__force u32)port, proto, ip_vs_conn_rnd)
& IP_VS_CONN_TAB_MASK;
#endif
return jhash_3words((__force u32)addr->ip, (__force u32)port, proto,
ip_vs_conn_rnd)
& IP_VS_CONN_TAB_MASK;
}

Expand All @@ -131,7 +140,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
int ret;

/* Hash by protocol, client address and port */
hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr.ip, cp->cport);
hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);

ct_write_lock(hash);

Expand Down Expand Up @@ -162,7 +171,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
int ret;

/* unhash it and decrease its reference counter */
hash = ip_vs_conn_hashkey(cp->protocol, cp->caddr.ip, cp->cport);
hash = ip_vs_conn_hashkey(cp->af, cp->protocol, &cp->caddr, cp->cport);

ct_write_lock(hash);

Expand All @@ -187,18 +196,21 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
* d_addr, d_port: pkt dest address (load balancer)
*/
static inline struct ip_vs_conn *__ip_vs_conn_in_get
(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port)
{
unsigned hash;
struct ip_vs_conn *cp;

hash = ip_vs_conn_hashkey(protocol, s_addr, s_port);
hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);

ct_read_lock(hash);

list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
if (s_addr == cp->caddr.ip && s_port == cp->cport &&
d_port == cp->vport && d_addr == cp->vaddr.ip &&
if (cp->af == af &&
ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
ip_vs_addr_equal(af, d_addr, &cp->vaddr) &&
s_port == cp->cport && d_port == cp->vport &&
((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
protocol == cp->protocol) {
/* HIT */
Expand All @@ -214,37 +226,42 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get
}

struct ip_vs_conn *ip_vs_conn_in_get
(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port)
{
struct ip_vs_conn *cp;

cp = __ip_vs_conn_in_get(protocol, s_addr, s_port, d_addr, d_port);
cp = __ip_vs_conn_in_get(af, protocol, s_addr, s_port, d_addr, d_port);
if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt))
cp = __ip_vs_conn_in_get(protocol, s_addr, 0, d_addr, d_port);
cp = __ip_vs_conn_in_get(af, protocol, s_addr, 0, d_addr,
d_port);

IP_VS_DBG(9, "lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
ip_vs_proto_name(protocol),
NIPQUAD(s_addr), ntohs(s_port),
NIPQUAD(d_addr), ntohs(d_port),
cp?"hit":"not hit");
IP_VS_DBG_BUF(9, "lookup/in %s %s:%d->%s:%d %s\n",
ip_vs_proto_name(protocol),
IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
cp ? "hit" : "not hit");

return cp;
}

/* Get reference to connection template */
struct ip_vs_conn *ip_vs_ct_in_get
(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port)
{
unsigned hash;
struct ip_vs_conn *cp;

hash = ip_vs_conn_hashkey(protocol, s_addr, s_port);
hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);

ct_read_lock(hash);

list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
if (s_addr == cp->caddr.ip && s_port == cp->cport &&
d_port == cp->vport && d_addr == cp->vaddr.ip &&
if (cp->af == af &&
ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
ip_vs_addr_equal(af, d_addr, &cp->vaddr) &&
s_port == cp->cport && d_port == cp->vport &&
cp->flags & IP_VS_CONN_F_TEMPLATE &&
protocol == cp->protocol) {
/* HIT */
Expand All @@ -257,11 +274,11 @@ struct ip_vs_conn *ip_vs_ct_in_get
out:
ct_read_unlock(hash);

IP_VS_DBG(9, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
ip_vs_proto_name(protocol),
NIPQUAD(s_addr), ntohs(s_port),
NIPQUAD(d_addr), ntohs(d_port),
cp?"hit":"not hit");
IP_VS_DBG_BUF(9, "template lookup/in %s %s:%d->%s:%d %s\n",
ip_vs_proto_name(protocol),
IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
cp ? "hit" : "not hit");

return cp;
}
Expand All @@ -273,21 +290,24 @@ struct ip_vs_conn *ip_vs_ct_in_get
* d_addr, d_port: pkt dest address (foreign host)
*/
struct ip_vs_conn *ip_vs_conn_out_get
(int protocol, __be32 s_addr, __be16 s_port, __be32 d_addr, __be16 d_port)
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port)
{
unsigned hash;
struct ip_vs_conn *cp, *ret=NULL;

/*
* Check for "full" addressed entries
*/
hash = ip_vs_conn_hashkey(protocol, d_addr, d_port);
hash = ip_vs_conn_hashkey(af, protocol, d_addr, d_port);

ct_read_lock(hash);

list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
if (d_addr == cp->caddr.ip && d_port == cp->cport &&
s_port == cp->dport && s_addr == cp->daddr.ip &&
if (cp->af == af &&
ip_vs_addr_equal(af, d_addr, &cp->caddr) &&
ip_vs_addr_equal(af, s_addr, &cp->daddr) &&
d_port == cp->cport && s_port == cp->dport &&
protocol == cp->protocol) {
/* HIT */
atomic_inc(&cp->refcnt);
Expand All @@ -298,11 +318,11 @@ struct ip_vs_conn *ip_vs_conn_out_get

ct_read_unlock(hash);

IP_VS_DBG(9, "lookup/out %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
ip_vs_proto_name(protocol),
NIPQUAD(s_addr), ntohs(s_port),
NIPQUAD(d_addr), ntohs(d_port),
ret?"hit":"not hit");
IP_VS_DBG_BUF(9, "lookup/out %s %s:%d->%s:%d %s\n",
ip_vs_proto_name(protocol),
IP_VS_DBG_ADDR(af, s_addr), ntohs(s_port),
IP_VS_DBG_ADDR(af, d_addr), ntohs(d_port),
ret ? "hit" : "not hit");

return ret;
}
Expand Down Expand Up @@ -625,8 +645,9 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
* Create a new connection entry and hash it into the ip_vs_conn_tab
*/
struct ip_vs_conn *
ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport,
__be32 daddr, __be16 dport, unsigned flags,
ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,
const union nf_inet_addr *vaddr, __be16 vport,
const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
struct ip_vs_dest *dest)
{
struct ip_vs_conn *cp;
Expand All @@ -640,12 +661,13 @@ ip_vs_conn_new(int proto, __be32 caddr, __be16 cport, __be32 vaddr, __be16 vport

INIT_LIST_HEAD(&cp->c_list);
setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
cp->af = af;
cp->protocol = proto;
cp->caddr.ip = caddr;
ip_vs_addr_copy(af, &cp->caddr, caddr);
cp->cport = cport;
cp->vaddr.ip = vaddr;
ip_vs_addr_copy(af, &cp->vaddr, vaddr);
cp->vport = vport;
cp->daddr.ip = daddr;
ip_vs_addr_copy(af, &cp->daddr, daddr);
cp->dport = dport;
cp->flags = flags;
spin_lock_init(&cp->lock);
Expand Down
Loading

0 comments on commit 28364a5

Please sign in to comment.