Hi Julian, On Sun, Mar 31, 2019 at 01:26:19PM +0300, Julian Anastasov wrote: > 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@xxxxxx> This looks good to me, modulo some nits below. > --- > include/net/ip_vs.h | 3 +++ > net/netfilter/ipvs/ip_vs_ctl.c | 43 +++++++++++++++++++++++++++------- > 2 files changed, 38 insertions(+), 8 deletions(-) > > diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h > index 2ac40135b576..9a8ac8997e34 100644 > --- a/include/net/ip_vs.h > +++ b/include/net/ip_vs.h > @@ -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) > > diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c > index 328683452229..7de90c00c8bd 100644 > --- a/net/netfilter/ipvs/ip_vs_ctl.c > +++ b/net/netfilter/ipvs/ip_vs_ctl.c > @@ -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)) { nit: there seem to be unnecessary () on the line above > /* 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)) { ditto > /* HIT */ > return dest; > } ...