net: tcp: raise zero-window probe without check wnd_end

In the origin logic, zero-window probe can not only be raised on
0 window, but also in other case, such as MTU probe fails.

Therefore, we need modify tcp_probe0_needed() to make it compatible
with origin logic.

Signed-off-by: Menglong Dong <imagedong@tencent.com>
This commit is contained in:
Menglong Dong 2023-05-06 20:26:45 +08:00 committed by Jianping Liu
parent 980a335360
commit f0d423d51c
2 changed files with 33 additions and 21 deletions

View File

@ -1831,29 +1831,35 @@ static inline bool tcp_rtx_and_write_queues_empty(const struct sock *sk)
return tcp_rtx_queue_empty(sk) && tcp_write_queue_empty(sk);
}
static inline bool __tcp_probe0_needed(const struct sock *sk)
{
return !tcp_sk(sk)->packets_out && !tcp_write_queue_empty(sk);
}
#ifdef CONFIG_TCP_WND_SHRINK
static inline bool tcp_rtx_overflow(const struct sock *sk)
{
struct sk_buff *rtx_head = tcp_rtx_queue_head(sk);
return rtx_head && after(TCP_SKB_CB(rtx_head)->end_seq,
tcp_wnd_end(tcp_sk(sk)));
}
/* check if 0 window probe is need by the sk */
static inline bool tcp_probe0_needed(const struct sock *sk)
{
struct sk_buff *rtx_head = tcp_rtx_queue_head(sk);
struct sk_buff *head = tcp_send_head(sk);
const struct tcp_sock *tp = tcp_sk(sk);
/* for the normal case */
if (__tcp_probe0_needed(sk))
return true;
if (rtx_head) {
if (after(TCP_SKB_CB(rtx_head)->end_seq, tcp_wnd_end(tp)))
return true;
} else {
if (head && after(TCP_SKB_CB(head)->end_seq,
tcp_wnd_end(tp)))
return true;
}
return false;
/* for the window shrink case */
return tcp_rtx_overflow(sk);
}
#else
static inline bool tcp_probe0_needed(const struct sock *sk)
{
return !tcp_sk(sk)->packets_out && !tcp_write_queue_empty(sk);
return __tcp_probe0_needed(sk);
}
#endif

View File

@ -3316,12 +3316,24 @@ static void tcp_ack_probe(struct sock *sk)
}
#ifdef CONFIG_TCP_WND_SHRINK
/**
* This function is called only when there are packets in the rtx queue,
* which means that the packets out is not 0.
*
* NOTE: we only handle window shrink case in this part.
*/
static void tcp_ack_probe_shrink(struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);
unsigned long when;
if (!tcp_probe0_needed(sk)) {
if (tcp_rtx_overflow(sk)) {
when = tcp_probe0_when(sk, TCP_RTO_MAX);
when = tcp_clamp_probe0_to_user_timeout(sk, when);
tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
when, TCP_RTO_MAX, NULL);
} else {
/* check if recover from window shrink */
if (icsk->icsk_pending != ICSK_TIME_PROBE0)
return;
@ -3331,12 +3343,6 @@ static void tcp_ack_probe_shrink(struct sock *sk)
inet_csk_clear_xmit_timer(sk, ICSK_TIME_PROBE0);
if (!tcp_rtx_queue_empty(sk))
tcp_retransmit_timer(sk);
} else {
when = tcp_probe0_when(sk, TCP_RTO_MAX);
when = tcp_clamp_probe0_to_user_timeout(sk, when);
tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
when, TCP_RTO_MAX, NULL);
}
}
#else