mirror of https://gitee.com/openkylin/linux.git
ipvs: allow rs_table to contain different real server types
Before now rs_table was used only for NAT real servers. Change it to allow TUN real severs from different types, possibly hashed with different port key. Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
7b3ed2a137
commit
1da40ab6ca
|
@ -1497,6 +1497,9 @@ static inline int ip_vs_todrop(struct netns_ipvs *ipvs)
|
|||
static inline int ip_vs_todrop(struct netns_ipvs *ipvs) { return 0; }
|
||||
#endif
|
||||
|
||||
#define IP_VS_DFWD_METHOD(dest) (atomic_read(&(dest)->conn_flags) & \
|
||||
IP_VS_CONN_F_FWD_MASK)
|
||||
|
||||
/* ip_vs_fwd_tag returns the forwarding tag of the connection */
|
||||
#define IP_VS_FWD_METHOD(cp) (cp->flags & IP_VS_CONN_F_FWD_MASK)
|
||||
|
||||
|
|
|
@ -515,15 +515,36 @@ static inline unsigned int ip_vs_rs_hashkey(int af,
|
|||
static void ip_vs_rs_hash(struct netns_ipvs *ipvs, struct ip_vs_dest *dest)
|
||||
{
|
||||
unsigned int hash;
|
||||
__be16 port;
|
||||
|
||||
if (dest->in_rs_table)
|
||||
return;
|
||||
|
||||
switch (IP_VS_DFWD_METHOD(dest)) {
|
||||
case IP_VS_CONN_F_MASQ:
|
||||
port = dest->port;
|
||||
break;
|
||||
case IP_VS_CONN_F_TUNNEL:
|
||||
switch (dest->tun_type) {
|
||||
case IP_VS_CONN_F_TUNNEL_TYPE_GUE:
|
||||
port = dest->tun_port;
|
||||
break;
|
||||
case IP_VS_CONN_F_TUNNEL_TYPE_IPIP:
|
||||
port = 0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash by proto,addr,port,
|
||||
* which are the parameters of the real service.
|
||||
*/
|
||||
hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port);
|
||||
hash = ip_vs_rs_hashkey(dest->af, &dest->addr, port);
|
||||
|
||||
hlist_add_head_rcu(&dest->d_list, &ipvs->rs_table[hash]);
|
||||
dest->in_rs_table = 1;
|
||||
|
@ -555,7 +576,8 @@ bool ip_vs_has_real_service(struct netns_ipvs *ipvs, int af, __u16 protocol,
|
|||
if (dest->port == dport &&
|
||||
dest->af == af &&
|
||||
ip_vs_addr_equal(af, &dest->addr, daddr) &&
|
||||
(dest->protocol == protocol || dest->vfwmark)) {
|
||||
(dest->protocol == protocol || dest->vfwmark) &&
|
||||
IP_VS_DFWD_METHOD(dest) == IP_VS_CONN_F_MASQ) {
|
||||
/* HIT */
|
||||
return true;
|
||||
}
|
||||
|
@ -585,7 +607,8 @@ struct ip_vs_dest *ip_vs_find_real_service(struct netns_ipvs *ipvs, int af,
|
|||
if (dest->port == dport &&
|
||||
dest->af == af &&
|
||||
ip_vs_addr_equal(af, &dest->addr, daddr) &&
|
||||
(dest->protocol == protocol || dest->vfwmark)) {
|
||||
(dest->protocol == protocol || dest->vfwmark) &&
|
||||
IP_VS_DFWD_METHOD(dest) == IP_VS_CONN_F_MASQ) {
|
||||
/* HIT */
|
||||
return dest;
|
||||
}
|
||||
|
@ -831,6 +854,13 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
|
|||
conn_flags = udest->conn_flags & IP_VS_CONN_F_DEST_MASK;
|
||||
conn_flags |= IP_VS_CONN_F_INACTIVE;
|
||||
|
||||
/* Need to rehash? */
|
||||
if ((udest->conn_flags & IP_VS_CONN_F_FWD_MASK) !=
|
||||
IP_VS_DFWD_METHOD(dest) ||
|
||||
udest->tun_type != dest->tun_type ||
|
||||
udest->tun_port != dest->tun_port)
|
||||
ip_vs_rs_unhash(dest);
|
||||
|
||||
/* set the tunnel info */
|
||||
dest->tun_type = udest->tun_type;
|
||||
dest->tun_port = udest->tun_port;
|
||||
|
@ -839,16 +869,13 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
|
|||
if ((conn_flags & IP_VS_CONN_F_FWD_MASK) != IP_VS_CONN_F_MASQ) {
|
||||
conn_flags |= IP_VS_CONN_F_NOOUTPUT;
|
||||
} else {
|
||||
/*
|
||||
* Put the real service in rs_table if not present.
|
||||
* For now only for NAT!
|
||||
*/
|
||||
ip_vs_rs_hash(ipvs, dest);
|
||||
/* FTP-NAT requires conntrack for mangling */
|
||||
if (svc->port == FTPPORT)
|
||||
ip_vs_register_conntrack(svc);
|
||||
}
|
||||
atomic_set(&dest->conn_flags, conn_flags);
|
||||
/* Put the real service in rs_table if not present. */
|
||||
ip_vs_rs_hash(ipvs, dest);
|
||||
|
||||
/* bind the service */
|
||||
old_svc = rcu_dereference_protected(dest->svc, 1);
|
||||
|
|
Loading…
Reference in New Issue