netfilter: ipvs: Fix reuse connection if RS weight is 0

[ Upstream commit c95c07836f ]

We are changing expire_nodest_conn to work even for reused connections when
conn_reuse_mode=0, just as what was done with commit dc7b3eb900 ("ipvs:
Fix reuse connection if real server is dead").

For controlled and persistent connections, the new connection will get the
needed real server depending on the rules in ip_vs_check_template().

Fixes: d752c36457 ("ipvs: allow rescheduling of new connections when port reuse is detected")
Co-developed-by: Chuanqi Liu <legend050709@qq.com>
Signed-off-by: Chuanqi Liu <legend050709@qq.com>
Signed-off-by: yangxingwu <xingwu.yang@gmail.com>
Acked-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
yangxingwu 2021-11-04 03:10:29 +01:00 committed by Greg Kroah-Hartman
parent 49f8783307
commit e76228cbec
2 changed files with 5 additions and 6 deletions

View File

@ -37,8 +37,7 @@ conn_reuse_mode - INTEGER
0: disable any special handling on port reuse. The new 0: disable any special handling on port reuse. The new
connection will be delivered to the same real server that was connection will be delivered to the same real server that was
servicing the previous connection. This will effectively servicing the previous connection.
disable expire_nodest_conn.
bit 1: enable rescheduling of new connections when it is safe. bit 1: enable rescheduling of new connections when it is safe.
That is, whenever expire_nodest_conn and for TCP sockets, when That is, whenever expire_nodest_conn and for TCP sockets, when

View File

@ -1964,7 +1964,6 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
struct ip_vs_proto_data *pd; struct ip_vs_proto_data *pd;
struct ip_vs_conn *cp; struct ip_vs_conn *cp;
int ret, pkts; int ret, pkts;
int conn_reuse_mode;
struct sock *sk; struct sock *sk;
/* Already marked as IPVS request or reply? */ /* Already marked as IPVS request or reply? */
@ -2041,15 +2040,16 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
cp = INDIRECT_CALL_1(pp->conn_in_get, ip_vs_conn_in_get_proto, cp = INDIRECT_CALL_1(pp->conn_in_get, ip_vs_conn_in_get_proto,
ipvs, af, skb, &iph); ipvs, af, skb, &iph);
conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); if (!iph.fragoffs && is_new_conn(skb, &iph) && cp) {
if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) { int conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
bool old_ct = false, resched = false; bool old_ct = false, resched = false;
if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest &&
unlikely(!atomic_read(&cp->dest->weight))) { unlikely(!atomic_read(&cp->dest->weight))) {
resched = true; resched = true;
old_ct = ip_vs_conn_uses_old_conntrack(cp, skb); old_ct = ip_vs_conn_uses_old_conntrack(cp, skb);
} else if (is_new_conn_expected(cp, conn_reuse_mode)) { } else if (conn_reuse_mode &&
is_new_conn_expected(cp, conn_reuse_mode)) {
old_ct = ip_vs_conn_uses_old_conntrack(cp, skb); old_ct = ip_vs_conn_uses_old_conntrack(cp, skb);
if (!atomic_read(&cp->n_control)) { if (!atomic_read(&cp->n_control)) {
resched = true; resched = true;