net: tcp: send zero-window when no memory
For now, skb will be dropped when no memory, which makes client keep retrans util timeout and it's not friendly to the users. Therefore, now we force to receive one packet on current socket when the protocol memory is out of the limitation. Then, this socket will stay in 'no mem' status, util protocol memory is available. When a socket is in 'no mem' status, it's receive window will become 0, which means window shrink happens. And the sender need to handle such window shrink properly, which is done in the next commit. Signed-off-by: Menglong Dong <imagedong@tencent.com>
This commit is contained in:
parent
1ea94d5505
commit
bb00f4ca4c
|
@ -868,6 +868,7 @@ enum sock_flags {
|
|||
SOCK_TXTIME,
|
||||
SOCK_XDP, /* XDP is attached */
|
||||
SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */
|
||||
SOCK_NO_MEM,
|
||||
};
|
||||
|
||||
#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
|
||||
|
|
|
@ -728,3 +728,14 @@ config TCP_MD5SIG
|
|||
on the Internet.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TCP_WND_SHRINK
|
||||
bool "TCP: Support window shrink when no memory"
|
||||
default y
|
||||
help
|
||||
Skb will be dropped when no memory, which makes client keep
|
||||
retrans util timeout and it's not friendly to the users. Enable
|
||||
this configuration will make the connection keep in zero-window
|
||||
probe state and avoid connection break.
|
||||
|
||||
If unsure, say N
|
||||
|
|
|
@ -4824,9 +4824,20 @@ queue_and_out:
|
|||
if (skb_queue_len(&sk->sk_receive_queue) == 0)
|
||||
sk_forced_mem_schedule(sk, skb->truesize);
|
||||
else if (tcp_try_rmem_schedule(sk, skb, skb->truesize)) {
|
||||
#ifdef CONFIG_TCP_WND_SHRINK
|
||||
if (sock_flag(sk, SOCK_NO_MEM)) {
|
||||
NET_INC_STATS(sock_net(sk),
|
||||
LINUX_MIB_TCPRCVQDROP);
|
||||
sk->sk_data_ready(sk);
|
||||
goto out_of_window;
|
||||
}
|
||||
sk_forced_mem_schedule(sk, skb->truesize);
|
||||
sock_set_flag(sk, SOCK_NO_MEM);
|
||||
#else
|
||||
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRCVQDROP);
|
||||
sk->sk_data_ready(sk);
|
||||
goto drop;
|
||||
#endif
|
||||
}
|
||||
|
||||
eaten = tcp_queue_rcv(sk, skb, &fragstolen);
|
||||
|
@ -4867,7 +4878,9 @@ out_of_window:
|
|||
NET_INC_DROPSTATS(sock_net(sk), LINUX_MIB_TCPOOWDROP);
|
||||
tcp_enter_quickack_mode(sk, TCP_MAX_QUICKACKS);
|
||||
inet_csk_schedule_ack(sk);
|
||||
#ifndef CONFIG_TCP_WND_SHRINK
|
||||
drop:
|
||||
#endif
|
||||
tcp_drop(sk, skb);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -301,6 +301,15 @@ static u16 tcp_select_window(struct sock *sk)
|
|||
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFROMZEROWINDOWADV);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCP_WND_SHRINK
|
||||
if (sock_flag(sk, SOCK_NO_MEM)) {
|
||||
if (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 2))
|
||||
sock_reset_flag(sk, SOCK_NO_MEM);
|
||||
else
|
||||
new_win = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return new_win;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue