Skip to content

Commit

Permalink
IPVS: Add struct ip_vs_conn_param
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
  • Loading branch information
Simon Horman committed Oct 4, 2010
1 parent 5b57a98 commit f11017e
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 203 deletions.
44 changes: 30 additions & 14 deletions include/net/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,15 @@ struct ip_vs_protocol {

extern struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto);

struct ip_vs_conn_param {
const union nf_inet_addr *caddr;
const union nf_inet_addr *vaddr;
__be16 cport;
__be16 vport;
__u16 protocol;
u16 af;
};

/*
* IP_VS structure allocated for each dynamically scheduled connection
*/
Expand Down Expand Up @@ -626,23 +635,31 @@ enum {
IP_VS_DIR_LAST,
};

extern struct ip_vs_conn *ip_vs_conn_in_get
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port);
static inline void ip_vs_conn_fill_param(int af, int protocol,
const union nf_inet_addr *caddr,
__be16 cport,
const union nf_inet_addr *vaddr,
__be16 vport,
struct ip_vs_conn_param *p)
{
p->af = af;
p->protocol = protocol;
p->caddr = caddr;
p->cport = cport;
p->vaddr = vaddr;
p->vport = vport;
}

extern struct ip_vs_conn *ip_vs_ct_in_get
(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 *ip_vs_conn_in_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);

struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph,
unsigned int proto_off,
int inverse);

extern struct ip_vs_conn *ip_vs_conn_out_get
(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 *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);

struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
Expand All @@ -658,11 +675,10 @@ static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
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 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 *ip_vs_conn_new(const struct ip_vs_conn_param *p,
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);

extern const char * ip_vs_state_name(__u16 proto, int state);
Expand Down
171 changes: 84 additions & 87 deletions net/netfilter/ipvs/ip_vs_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,27 +218,26 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
/*
* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
* Called for pkts coming from OUTside-to-INside.
* s_addr, s_port: pkt source address (foreign host)
* d_addr, d_port: pkt dest address (load balancer)
* p->caddr, p->cport: pkt source address (foreign host)
* p->vaddr, p->vport: pkt dest address (load balancer)
*/
static inline struct ip_vs_conn *__ip_vs_conn_in_get
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port)
static inline struct ip_vs_conn *
__ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
{
unsigned hash;
struct ip_vs_conn *cp;

hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport);

ct_read_lock(hash);

list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
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) {
if (cp->af == p->af &&
ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
ip_vs_addr_equal(p->af, p->vaddr, &cp->vaddr) &&
p->cport == cp->cport && p->vport == cp->vport &&
((!p->cport) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
p->protocol == cp->protocol) {
/* HIT */
atomic_inc(&cp->refcnt);
ct_read_unlock(hash);
Expand All @@ -251,71 +250,82 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get
return NULL;
}

struct ip_vs_conn *ip_vs_conn_in_get
(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 *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
{
struct ip_vs_conn *cp;

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(af, protocol, s_addr, 0, d_addr,
d_port);
cp = __ip_vs_conn_in_get(p);
if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt)) {
struct ip_vs_conn_param cport_zero_p = *p;
cport_zero_p.cport = 0;
cp = __ip_vs_conn_in_get(&cport_zero_p);
}

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),
ip_vs_proto_name(p->protocol),
IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
cp ? "hit" : "not hit");

return cp;
}

static int
ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
unsigned int proto_off, int inverse,
struct ip_vs_conn_param *p)
{
__be16 _ports[2], *pptr;

pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
if (pptr == NULL)
return 1;

if (likely(!inverse))
ip_vs_conn_fill_param(af, iph->protocol, &iph->saddr, pptr[0],
&iph->daddr, pptr[1], p);
else
ip_vs_conn_fill_param(af, iph->protocol, &iph->daddr, pptr[1],
&iph->saddr, pptr[0], p);
return 0;
}

struct ip_vs_conn *
ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
struct ip_vs_protocol *pp,
const struct ip_vs_iphdr *iph,
unsigned int proto_off, int inverse)
{
__be16 _ports[2], *pptr;
struct ip_vs_conn_param p;

pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
if (pptr == NULL)
if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
return NULL;

if (likely(!inverse))
return ip_vs_conn_in_get(af, iph->protocol,
&iph->saddr, pptr[0],
&iph->daddr, pptr[1]);
else
return ip_vs_conn_in_get(af, iph->protocol,
&iph->daddr, pptr[1],
&iph->saddr, pptr[0]);
return ip_vs_conn_in_get(&p);
}
EXPORT_SYMBOL_GPL(ip_vs_conn_in_get_proto);

/* Get reference to connection template */
struct ip_vs_conn *ip_vs_ct_in_get
(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 *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
{
unsigned hash;
struct ip_vs_conn *cp;

hash = ip_vs_conn_hashkey(af, protocol, s_addr, s_port);
hash = ip_vs_conn_hashkey(p->af, p->protocol, p->caddr, p->cport);

ct_read_lock(hash);

list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
if (cp->af == af &&
ip_vs_addr_equal(af, s_addr, &cp->caddr) &&
if (cp->af == p->af &&
ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
/* protocol should only be IPPROTO_IP if
* d_addr is a fwmark */
ip_vs_addr_equal(protocol == IPPROTO_IP ? AF_UNSPEC : af,
d_addr, &cp->vaddr) &&
s_port == cp->cport && d_port == cp->vport &&
* p->vaddr is a fwmark */
ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC :
p->af, p->vaddr, &cp->vaddr) &&
p->cport == cp->cport && p->vport == cp->vport &&
cp->flags & IP_VS_CONN_F_TEMPLATE &&
protocol == cp->protocol) {
p->protocol == cp->protocol) {
/* HIT */
atomic_inc(&cp->refcnt);
goto out;
Expand All @@ -327,40 +337,36 @@ struct ip_vs_conn *ip_vs_ct_in_get
ct_read_unlock(hash);

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),
ip_vs_proto_name(p->protocol),
IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
cp ? "hit" : "not hit");

return cp;
}

/*
* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
* Called for pkts coming from inside-to-OUTside.
* s_addr, s_port: pkt source address (inside host)
* d_addr, d_port: pkt dest address (foreign host)
*/
struct ip_vs_conn *ip_vs_conn_out_get
(int af, int protocol, const union nf_inet_addr *s_addr, __be16 s_port,
const union nf_inet_addr *d_addr, __be16 d_port)
/* Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab.
* Called for pkts coming from inside-to-OUTside.
* p->caddr, p->cport: pkt source address (inside host)
* p->vaddr, p->vport: pkt dest address (foreign host) */
struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
{
unsigned hash;
struct ip_vs_conn *cp, *ret=NULL;

/*
* Check for "full" addressed entries
*/
hash = ip_vs_conn_hashkey(af, protocol, d_addr, d_port);
hash = ip_vs_conn_hashkey(p->af, p->protocol, p->vaddr, p->vport);

ct_read_lock(hash);

list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
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) {
if (cp->af == p->af &&
ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) &&
ip_vs_addr_equal(p->af, p->caddr, &cp->daddr) &&
p->vport == cp->cport && p->cport == cp->dport &&
p->protocol == cp->protocol) {
/* HIT */
atomic_inc(&cp->refcnt);
ret = cp;
Expand All @@ -371,9 +377,9 @@ struct ip_vs_conn *ip_vs_conn_out_get
ct_read_unlock(hash);

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),
ip_vs_proto_name(p->protocol),
IP_VS_DBG_ADDR(p->af, p->caddr), ntohs(p->cport),
IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
ret ? "hit" : "not hit");

return ret;
Expand All @@ -385,20 +391,12 @@ ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
unsigned int proto_off, int inverse)
{
__be16 _ports[2], *pptr;
struct ip_vs_conn_param p;

pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
if (pptr == NULL)
if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
return NULL;

if (likely(!inverse))
return ip_vs_conn_out_get(af, iph->protocol,
&iph->saddr, pptr[0],
&iph->daddr, pptr[1]);
else
return ip_vs_conn_out_get(af, iph->protocol,
&iph->daddr, pptr[1],
&iph->saddr, pptr[0]);
return ip_vs_conn_out_get(&p);
}
EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);

Expand Down Expand Up @@ -758,13 +756,12 @@ 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 af, int proto, const union nf_inet_addr *caddr, __be16 cport,
const union nf_inet_addr *vaddr, __be16 vport,
ip_vs_conn_new(const struct ip_vs_conn_param *p,
const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
struct ip_vs_dest *dest)
{
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp = ip_vs_proto_get(proto);
struct ip_vs_protocol *pp = ip_vs_proto_get(p->protocol);

cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC);
if (cp == NULL) {
Expand All @@ -774,14 +771,14 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,

INIT_LIST_HEAD(&cp->c_list);
setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
cp->af = af;
cp->protocol = proto;
ip_vs_addr_copy(af, &cp->caddr, caddr);
cp->cport = cport;
ip_vs_addr_copy(af, &cp->vaddr, vaddr);
cp->vport = vport;
cp->af = p->af;
cp->protocol = p->protocol;
ip_vs_addr_copy(p->af, &cp->caddr, p->caddr);
cp->cport = p->cport;
ip_vs_addr_copy(p->af, &cp->vaddr, p->vaddr);
cp->vport = p->vport;
/* proto should only be IPPROTO_IP if d_addr is a fwmark */
ip_vs_addr_copy(proto == IPPROTO_IP ? AF_UNSPEC : af,
ip_vs_addr_copy(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
&cp->daddr, daddr);
cp->dport = dport;
cp->flags = flags;
Expand Down Expand Up @@ -810,7 +807,7 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport,

/* Bind its packet transmitter */
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
if (p->af == AF_INET6)
ip_vs_bind_xmit_v6(cp);
else
#endif
Expand Down
Loading

0 comments on commit f11017e

Please sign in to comment.