mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
Merge branch 'tcp-rfc-7323-compliant-window-retraction-handling'
Simon Baatz says: ==================== tcp: RFC 7323-compliant window retraction handling this series implements the receiver-side requirements for TCP window retraction as specified in RFC 7323 and adds packetdrill tests to cover the new behavior. Please see the first patch for background and implementation details. Since MPTCP adjusts the TCP receive window on subflows, the relevant MPTCP code paths are updated accordingly. ==================== Link: https://patch.msgid.link/20260309-tcp_rfc7323_retract_wnd_rfc-v3-0-4c7f96b1ec69@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
b58e3a2d01
|
|
@ -121,6 +121,7 @@ u64 delivered_mstamp read_write
|
|||
u32 rate_delivered read_mostly tcp_rate_gen
|
||||
u32 rate_interval_us read_mostly rate_delivered,rate_app_limited
|
||||
u32 rcv_wnd read_write read_mostly tcp_select_window,tcp_receive_window,tcp_fast_path_check
|
||||
u32 rcv_mwnd_seq read_write tcp_select_window
|
||||
u32 write_seq read_write tcp_rate_check_app_limited,tcp_write_queue_empty,tcp_skb_entail,forced_push,tcp_mark_push
|
||||
u32 notsent_lowat read_mostly tcp_stream_memory_free
|
||||
u32 pushed_seq read_write tcp_mark_push,forced_push
|
||||
|
|
|
|||
|
|
@ -316,6 +316,9 @@ struct tcp_sock {
|
|||
*/
|
||||
u32 app_limited; /* limited until "delivered" reaches this val */
|
||||
u32 rcv_wnd; /* Current receiver window */
|
||||
u32 rcv_mwnd_seq; /* Maximum window sequence number (RFC 7323,
|
||||
* section 2.4, receiver requirements)
|
||||
*/
|
||||
u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
|
||||
/*
|
||||
* Options received (usually on last packet, some only on SYN packets).
|
||||
|
|
|
|||
|
|
@ -934,6 +934,28 @@ static inline u32 tcp_receive_window(const struct tcp_sock *tp)
|
|||
return (u32) win;
|
||||
}
|
||||
|
||||
/* Compute the maximum receive window we ever advertised.
|
||||
* Rcv_nxt can be after the window if our peer push more data
|
||||
* than the offered window.
|
||||
*/
|
||||
static inline u32 tcp_max_receive_window(const struct tcp_sock *tp)
|
||||
{
|
||||
s32 win = tp->rcv_mwnd_seq - tp->rcv_nxt;
|
||||
|
||||
if (win < 0)
|
||||
win = 0;
|
||||
return (u32) win;
|
||||
}
|
||||
|
||||
/* Check if we need to update the maximum receive window sequence number */
|
||||
static inline void tcp_update_max_rcv_wnd_seq(struct tcp_sock *tp)
|
||||
{
|
||||
u32 wre = tp->rcv_wup + tp->rcv_wnd;
|
||||
|
||||
if (after(wre, tp->rcv_mwnd_seq))
|
||||
tp->rcv_mwnd_seq = wre;
|
||||
}
|
||||
|
||||
/* Choose a new window, without checks for shrinking, and without
|
||||
* scaling applied to the result. The caller does these things
|
||||
* if necessary. This is a "raw" window selection.
|
||||
|
|
|
|||
|
|
@ -3561,6 +3561,7 @@ static int tcp_repair_set_window(struct tcp_sock *tp, sockptr_t optbuf, int len)
|
|||
|
||||
tp->rcv_wnd = opt.rcv_wnd;
|
||||
tp->rcv_wup = opt.rcv_wup;
|
||||
tp->rcv_mwnd_seq = opt.rcv_wup + opt.rcv_wnd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -5275,6 +5276,7 @@ static void __init tcp_struct_check(void)
|
|||
CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_write_txrx, received_ecn_bytes);
|
||||
CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_write_txrx, app_limited);
|
||||
CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_write_txrx, rcv_wnd);
|
||||
CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_write_txrx, rcv_mwnd_seq);
|
||||
CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_write_txrx, rcv_tstamp);
|
||||
CACHELINE_ASSERT_GROUP_MEMBER(struct tcp_sock, tcp_sock_write_txrx, rx_opt);
|
||||
|
||||
|
|
|
|||
|
|
@ -377,6 +377,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
|
|||
|
||||
tcp_rsk(req)->rcv_nxt = tp->rcv_nxt;
|
||||
tp->rcv_wup = tp->rcv_nxt;
|
||||
tp->rcv_mwnd_seq = tp->rcv_wup + tp->rcv_wnd;
|
||||
/* tcp_conn_request() is sending the SYNACK,
|
||||
* and queues the child into listener accept queue.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4808,20 +4808,18 @@ static enum skb_drop_reason tcp_sequence(const struct sock *sk,
|
|||
const struct tcphdr *th)
|
||||
{
|
||||
const struct tcp_sock *tp = tcp_sk(sk);
|
||||
u32 seq_limit;
|
||||
|
||||
if (before(end_seq, tp->rcv_wup))
|
||||
return SKB_DROP_REASON_TCP_OLD_SEQUENCE;
|
||||
|
||||
seq_limit = tp->rcv_nxt + tcp_receive_window(tp);
|
||||
if (unlikely(after(end_seq, seq_limit))) {
|
||||
if (unlikely(after(end_seq, tp->rcv_nxt + tcp_max_receive_window(tp)))) {
|
||||
/* Some stacks are known to handle FIN incorrectly; allow the
|
||||
* FIN to extend beyond the window and check it in detail later.
|
||||
*/
|
||||
if (!after(end_seq - th->fin, seq_limit))
|
||||
if (!after(end_seq - th->fin, tp->rcv_nxt + tcp_receive_window(tp)))
|
||||
return SKB_NOT_DROPPED_YET;
|
||||
|
||||
if (after(seq, seq_limit))
|
||||
if (after(seq, tp->rcv_nxt + tcp_max_receive_window(tp)))
|
||||
return SKB_DROP_REASON_TCP_INVALID_SEQUENCE;
|
||||
|
||||
/* Only accept this packet if receive queue is empty. */
|
||||
|
|
@ -5680,6 +5678,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
|
|||
if (!before(TCP_SKB_CB(skb)->seq,
|
||||
tp->rcv_nxt + tcp_receive_window(tp))) {
|
||||
reason = SKB_DROP_REASON_TCP_OVERWINDOW;
|
||||
NET_INC_STATS(sock_net(sk), LINUX_MIB_BEYOND_WINDOW);
|
||||
goto out_of_window;
|
||||
}
|
||||
|
||||
|
|
@ -6903,6 +6902,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
|
|||
*/
|
||||
WRITE_ONCE(tp->rcv_nxt, TCP_SKB_CB(skb)->seq + 1);
|
||||
tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
|
||||
tp->rcv_mwnd_seq = tp->rcv_wup + tp->rcv_wnd;
|
||||
|
||||
/* RFC1323: The window in SYN & SYN/ACK segments is
|
||||
* never scaled.
|
||||
|
|
@ -7015,6 +7015,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
|
|||
WRITE_ONCE(tp->rcv_nxt, TCP_SKB_CB(skb)->seq + 1);
|
||||
WRITE_ONCE(tp->copied_seq, tp->rcv_nxt);
|
||||
tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
|
||||
tp->rcv_mwnd_seq = tp->rcv_wup + tp->rcv_wnd;
|
||||
|
||||
/* RFC1323: The window in SYN & SYN/ACK segments is
|
||||
* never scaled.
|
||||
|
|
|
|||
|
|
@ -604,6 +604,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
|
|||
newtp->window_clamp = req->rsk_window_clamp;
|
||||
newtp->rcv_ssthresh = req->rsk_rcv_wnd;
|
||||
newtp->rcv_wnd = req->rsk_rcv_wnd;
|
||||
newtp->rcv_mwnd_seq = newtp->rcv_wup + req->rsk_rcv_wnd;
|
||||
newtp->rx_opt.wscale_ok = ireq->wscale_ok;
|
||||
if (newtp->rx_opt.wscale_ok) {
|
||||
newtp->rx_opt.snd_wscale = ireq->snd_wscale;
|
||||
|
|
|
|||
|
|
@ -293,6 +293,7 @@ static u16 tcp_select_window(struct sock *sk)
|
|||
tp->pred_flags = 0;
|
||||
tp->rcv_wnd = 0;
|
||||
tp->rcv_wup = tp->rcv_nxt;
|
||||
tcp_update_max_rcv_wnd_seq(tp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -316,6 +317,7 @@ static u16 tcp_select_window(struct sock *sk)
|
|||
|
||||
tp->rcv_wnd = new_win;
|
||||
tp->rcv_wup = tp->rcv_nxt;
|
||||
tcp_update_max_rcv_wnd_seq(tp);
|
||||
|
||||
/* Make sure we do not exceed the maximum possible
|
||||
* scaled window.
|
||||
|
|
@ -4165,6 +4167,7 @@ static void tcp_connect_init(struct sock *sk)
|
|||
else
|
||||
tp->rcv_tstamp = tcp_jiffies32;
|
||||
tp->rcv_wup = tp->rcv_nxt;
|
||||
tp->rcv_mwnd_seq = tp->rcv_nxt + tp->rcv_wnd;
|
||||
WRITE_ONCE(tp->copied_seq, tp->rcv_nxt);
|
||||
|
||||
inet_csk(sk)->icsk_rto = tcp_timeout_init(sk);
|
||||
|
|
|
|||
|
|
@ -1076,6 +1076,7 @@ static void rwin_update(struct mptcp_sock *msk, struct sock *ssk,
|
|||
* resync.
|
||||
*/
|
||||
tp->rcv_wnd += mptcp_rcv_wnd - subflow->rcv_wnd_sent;
|
||||
tcp_update_max_rcv_wnd_seq(tp);
|
||||
subflow->rcv_wnd_sent = mptcp_rcv_wnd;
|
||||
}
|
||||
|
||||
|
|
@ -1338,8 +1339,9 @@ static void mptcp_set_rwin(struct tcp_sock *tp, struct tcphdr *th)
|
|||
*/
|
||||
rcv_wnd_new = rcv_wnd_old;
|
||||
win = rcv_wnd_old - ack_seq;
|
||||
tp->rcv_wnd = min_t(u64, win, U32_MAX);
|
||||
new_win = tp->rcv_wnd;
|
||||
new_win = min_t(u64, win, U32_MAX);
|
||||
tp->rcv_wnd = new_win;
|
||||
tcp_update_max_rcv_wnd_seq(tp);
|
||||
|
||||
/* Make sure we do not exceed the maximum possible
|
||||
* scaled window.
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
+0 read(4, ..., 100000) = 4000
|
||||
|
||||
// If queue is empty, accept a packet even if its end_seq is above wup + rcv_wnd
|
||||
// If queue is empty, accept a packet even if its end_seq is above rcv_mwnd_seq
|
||||
+0 < P. 4001:54001(50000) ack 1 win 257
|
||||
* > . 1:1(0) ack 54001 win 0
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
--mss=1000
|
||||
|
||||
`./defaults.sh`
|
||||
|
||||
// Establish a connection.
|
||||
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
|
||||
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
|
||||
+0 setsockopt(3, SOL_SOCKET, SO_RCVBUF, [20000], 4) = 0
|
||||
+0 bind(3, ..., ...) = 0
|
||||
+0 listen(3, 1) = 0
|
||||
|
||||
+0 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
|
||||
+0 > S. 0:0(0) ack 1 win 18980 <mss 1460,nop,wscale 0>
|
||||
+.1 < . 1:1(0) ack 1 win 257
|
||||
|
||||
+0 accept(3, ..., ...) = 4
|
||||
|
||||
// A too big packet is accepted if the receive queue is empty
|
||||
+0 < P. 1:20001(20000) ack 1 win 257
|
||||
// Send a RST immediately so that there is no rcv_wup/rcv_mwnd_seq update yet
|
||||
+0 < R. 20001:20001(0) ack 1 win 257
|
||||
|
||||
+.1 %{ assert tcpi_state == TCP_CLOSE, tcpi_state }%
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
--mss=1000
|
||||
|
||||
`./defaults.sh
|
||||
sysctl -q net.ipv4.tcp_shrink_window=1
|
||||
sysctl -q net.ipv4.tcp_rmem="4096 32768 $((32*1024*1024))"`
|
||||
|
||||
0 `nstat -n`
|
||||
|
||||
// Establish a connection.
|
||||
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
|
||||
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
|
||||
+0 bind(3, ..., ...) = 0
|
||||
+0 listen(3, 1) = 0
|
||||
|
||||
+0 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
|
||||
+0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 10>
|
||||
+0 < . 1:1(0) ack 1 win 257
|
||||
|
||||
+0 accept(3, ..., ...) = 4
|
||||
|
||||
+0 < P. 1:10001(10000) ack 1 win 257
|
||||
* > . 1:1(0) ack 10001 win 15
|
||||
|
||||
+0 < P. 10001:11024(1023) ack 1 win 257
|
||||
* > . 1:1(0) ack 11024 win 13
|
||||
|
||||
// Max window seq advertised 10001 + 15*1024 = 25361, last advertised: 11024 + 13*1024 = 24336
|
||||
|
||||
// Segment beyond the max window is dropped
|
||||
+0 < P. 11024:25362(14338) ack 1 win 257
|
||||
* > . 1:1(0) ack 11024 win 13
|
||||
|
||||
// Segment using the max window is accepted
|
||||
+0 < P. 11024:25361(14337) ack 1 win 257
|
||||
* > . 1:1(0) ack 25361 win 0
|
||||
|
||||
// Check LINUX_MIB_BEYOND_WINDOW has been incremented once
|
||||
+0 `nstat | grep TcpExtBeyondWindow | grep -q " 1 "`
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// When tcp_receive_window() < tcp_max_receive_window(), tcp_sequence() accepts
|
||||
// packets that would be dropped under normal conditions (i.e. tcp_receive_window()
|
||||
// equal to tcp_max_receive_window()).
|
||||
// Test that such packets are handled as expected for RWIN == 0 and for RWIN > 0.
|
||||
|
||||
--mss=1000
|
||||
|
||||
`./defaults.sh`
|
||||
|
||||
0 `nstat -n`
|
||||
|
||||
// Establish a connection.
|
||||
+0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
|
||||
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
|
||||
+0 setsockopt(3, SOL_SOCKET, SO_RCVBUF, [1000000], 4) = 0
|
||||
+0 bind(3, ..., ...) = 0
|
||||
+0 listen(3, 1) = 0
|
||||
|
||||
+0 < S 0:0(0) win 32792 <mss 1000,nop,nop,sackOK,nop,wscale 7>
|
||||
+0 > S. 0:0(0) ack 1 win 65535 <mss 1460,nop,nop,sackOK,nop,wscale 4>
|
||||
+0 < . 1:1(0) ack 1 win 257
|
||||
|
||||
+0 accept(3, ..., ...) = 4
|
||||
|
||||
// Put 1040000 bytes into the receive buffer
|
||||
+0 < P. 1:65001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 65001
|
||||
+0 < P. 65001:130001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 130001
|
||||
+0 < P. 130001:195001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 195001
|
||||
+0 < P. 195001:260001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 260001
|
||||
+0 < P. 260001:325001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 325001
|
||||
+0 < P. 325001:390001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 390001
|
||||
+0 < P. 390001:455001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 455001
|
||||
+0 < P. 455001:520001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 520001
|
||||
+0 < P. 520001:585001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 585001
|
||||
+0 < P. 585001:650001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 650001
|
||||
+0 < P. 650001:715001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 715001
|
||||
+0 < P. 715001:780001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 780001
|
||||
+0 < P. 780001:845001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 845001
|
||||
+0 < P. 845001:910001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 910001
|
||||
+0 < P. 910001:975001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 975001
|
||||
+0 < P. 975001:1040001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 1040001
|
||||
|
||||
// Trigger an extreme memory squeeze by shrinking SO_RCVBUF
|
||||
+0 setsockopt(4, SOL_SOCKET, SO_RCVBUF, [16000], 4) = 0
|
||||
|
||||
+0 < P. 1040001:1105001(65000) ack 1 win 257
|
||||
* > . 1:1(0) ack 1040001 win 0
|
||||
// Check LINUX_MIB_TCPRCVQDROP has been incremented
|
||||
+0 `nstat -s | grep TcpExtTCPRcvQDrop| grep -q " 1 "`
|
||||
|
||||
// RWIN == 0: rcv_wup = 1040001, rcv_wnd = 0, rcv_mwnd_seq > 1105001 (significantly larger, typically ~1970000)
|
||||
|
||||
// Accept pure ack with seq in max adv. window
|
||||
+0 write(4, ..., 1000) = 1000
|
||||
+0 > P. 1:1001(1000) ack 1040001 win 0
|
||||
+0 < . 1105001:1105001(0) ack 1001 win 257
|
||||
|
||||
// In order segment, in max adv. window -> drop (SKB_DROP_REASON_TCP_ZEROWINDOW)
|
||||
+0 < P. 1040001:1041001(1000) ack 1001 win 257
|
||||
+0 > . 1001:1001(0) ack 1040001 win 0
|
||||
// Ooo partial segment, in max adv. window -> drop (SKB_DROP_REASON_TCP_ZEROWINDOW)
|
||||
+0 < P. 1039001:1041001(2000) ack 1001 win 257
|
||||
+0 > . 1001:1001(0) ack 1040001 win 0 <nop,nop,sack 1039001:1040001>
|
||||
// Check LINUX_MIB_TCPZEROWINDOWDROP has been incremented twice
|
||||
+0 `nstat -s | grep TcpExtTCPZeroWindowDrop| grep -q " 2 "`
|
||||
|
||||
// Ooo segment, in max adv. window -> drop (SKB_DROP_REASON_TCP_OVERWINDOW)
|
||||
+0 < P. 1105001:1106001(1000) ack 1001 win 257
|
||||
+0 > . 1001:1001(0) ack 1040001 win 0
|
||||
// Ooo segment, beyond max adv. window -> drop (SKB_DROP_REASON_TCP_INVALID_SEQUENCE)
|
||||
+0 < P. 2000001:2001001(1000) ack 1001 win 257
|
||||
+0 > . 1001:1001(0) ack 1040001 win 0
|
||||
// Check LINUX_MIB_BEYOND_WINDOW has been incremented twice
|
||||
+0 `nstat -s | grep TcpExtBeyondWindow | grep -q " 2 "`
|
||||
|
||||
// Read all data
|
||||
+0 read(4, ..., 2000000) = 1040000
|
||||
* > . 1001:1001(0) ack 1040001
|
||||
|
||||
// RWIN > 0: rcv_wup = 1040001, 0 < rcv_wnd < 32000, rcv_mwnd_seq > 1105001 (significantly larger, typically ~1970000)
|
||||
|
||||
// Accept pure ack with seq in max adv. window, beyond adv. window
|
||||
+0 write(4, ..., 1000) = 1000
|
||||
+0 > P. 1001:2001(1000) ack 1040001
|
||||
+0 < . 1105001:1105001(0) ack 2001 win 257
|
||||
|
||||
// In order segment, in max adv. window, in adv. window -> accept
|
||||
// Note: This also ensures that we cannot hit the empty queue exception in tcp_sequence() in the following tests
|
||||
+0 < P. 1040001:1041001(1000) ack 2001 win 257
|
||||
* > . 2001:2001(0) ack 1041001
|
||||
|
||||
// Ooo partial segment, in adv. window -> accept
|
||||
+0 < P. 1040001:1042001(2000) ack 2001 win 257
|
||||
+0 > . 2001:2001(0) ack 1042001 <nop,nop,sack 1040001:1041001>
|
||||
|
||||
// Ooo segment, in max adv. window, beyond adv. window -> drop (SKB_DROP_REASON_TCP_OVERWINDOW)
|
||||
+0 < P. 1105001:1106001(1000) ack 2001 win 257
|
||||
+0 > . 2001:2001(0) ack 1042001
|
||||
// Ooo segment, beyond max adv. window, beyond adv. window -> drop (SKB_DROP_REASON_TCP_INVALID_SEQUENCE)
|
||||
+0 < P. 2000001:2001001(1000) ack 2001 win 257
|
||||
+0 > . 2001:2001(0) ack 1042001
|
||||
// Check LINUX_MIB_BEYOND_WINDOW has been incremented twice
|
||||
+0 `nstat -s | grep TcpExtBeyondWindow | grep -q " 4 "`
|
||||
|
||||
// We are allowed to go beyond the window and buffer with one packet
|
||||
+0 < P. 1042001:1062001(20000) ack 2001 win 257
|
||||
* > . 2001:2001(0) ack 1062001
|
||||
+0 < P. 1062001:1082001(20000) ack 2001 win 257
|
||||
* > . 2001:2001(0) ack 1082001 win 0
|
||||
|
||||
// But not more: In order segment, in max adv. window -> drop (SKB_DROP_REASON_TCP_ZEROWINDOW)
|
||||
+0 < P. 1082001:1083001(1000) ack 2001 win 257
|
||||
* > . 2001:2001(0) ack 1082001
|
||||
// Check LINUX_MIB_TCPZEROWINDOWDROP has been incremented again
|
||||
+0 `nstat -s | grep TcpExtTCPZeroWindowDrop| grep -q " 3 "`
|
||||
Loading…
Reference in New Issue
Block a user