Skip to content

Commit 8537ad2

Browse files
Julian Anastasovgeekmaster21
Julian Anastasov
authored andcommitted
ipvs: allow connection reuse for unconfirmed conntrack
[ Upstream commit f0a5e4d7a594e0fe237d3dfafb069bb82f80f42f ] YangYuxi is reporting that connection reuse is causing one-second delay when SYN hits existing connection in TIME_WAIT state. Such delay was added to give time to expire both the IPVS connection and the corresponding conntrack. This was considered a rare case at that time but it is causing problem for some environments such as Kubernetes. As nf_conntrack_tcp_packet() can decide to release the conntrack in TIME_WAIT state and to replace it with a fresh NEW conntrack, we can use this to allow rescheduling just by tuning our check: if the conntrack is confirmed we can not schedule it to different real server and the one-second delay still applies but if new conntrack was created, we are free to select new real server without any delays. YangYuxi lists some of the problem reports: - One second connection delay in masquerading mode: https://marc.info/?t=151683118100004&r=1&w=2 - IPVS low throughput #70747 kubernetes/kubernetes#70747 - Apache Bench can fill up ipvs service proxy in seconds #544 cloudnativelabs/kube-router#544 - Additional 1s latency in `host -> service IP -> pod` kubernetes/kubernetes#90854 Fixes: f719e3754ee2 ("ipvs: drop first packet to redirect conntrack") Co-developed-by: YangYuxi <[email protected]> Signed-off-by: YangYuxi <[email protected]> Signed-off-by: Julian Anastasov <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent f9b0d94 commit 8537ad2

File tree

2 files changed

+11
-11
lines changed

2 files changed

+11
-11
lines changed

include/net/ip_vs.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,18 +1607,16 @@ static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
16071607
}
16081608
#endif /* CONFIG_IP_VS_NFCT */
16091609

1610-
/* Really using conntrack? */
1611-
static inline bool ip_vs_conn_uses_conntrack(struct ip_vs_conn *cp,
1612-
struct sk_buff *skb)
1610+
/* Using old conntrack that can not be redirected to another real server? */
1611+
static inline bool ip_vs_conn_uses_old_conntrack(struct ip_vs_conn *cp,
1612+
struct sk_buff *skb)
16131613
{
16141614
#ifdef CONFIG_IP_VS_NFCT
16151615
enum ip_conntrack_info ctinfo;
16161616
struct nf_conn *ct;
16171617

1618-
if (!(cp->flags & IP_VS_CONN_F_NFCT))
1619-
return false;
16201618
ct = nf_ct_get(skb, &ctinfo);
1621-
if (ct)
1619+
if (ct && nf_ct_is_confirmed(ct))
16221620
return true;
16231621
#endif
16241622
return false;

net/netfilter/ipvs/ip_vs_core.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,30 +1916,32 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
19161916

19171917
conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
19181918
if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) {
1919-
bool uses_ct = false, resched = false;
1919+
bool old_ct = false, resched = false;
19201920

19211921
if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest &&
19221922
unlikely(!atomic_read(&cp->dest->weight))) {
19231923
resched = true;
1924-
uses_ct = ip_vs_conn_uses_conntrack(cp, skb);
1924+
old_ct = ip_vs_conn_uses_old_conntrack(cp, skb);
19251925
} else if (is_new_conn_expected(cp, conn_reuse_mode)) {
1926-
uses_ct = ip_vs_conn_uses_conntrack(cp, skb);
1926+
old_ct = ip_vs_conn_uses_old_conntrack(cp, skb);
19271927
if (!atomic_read(&cp->n_control)) {
19281928
resched = true;
19291929
} else {
19301930
/* Do not reschedule controlling connection
19311931
* that uses conntrack while it is still
19321932
* referenced by controlled connection(s).
19331933
*/
1934-
resched = !uses_ct;
1934+
resched = !old_ct;
19351935
}
19361936
}
19371937

19381938
if (resched) {
1939+
if (!old_ct)
1940+
cp->flags &= ~IP_VS_CONN_F_NFCT;
19391941
if (!atomic_read(&cp->n_control))
19401942
ip_vs_conn_expire_now(cp);
19411943
__ip_vs_conn_put(cp);
1942-
if (uses_ct)
1944+
if (old_ct)
19431945
return NF_DROP;
19441946
cp = NULL;
19451947
}

0 commit comments

Comments
 (0)