Commit 49d09007879ce7bee36ab453c73e97c00adce884

Authored by Eric Dumazet
Committed by David S. Miller
1 parent 3320eae51d

tcp: diag: Dont report negative values for rx queue

Both netlink and /proc/net/tcp interfaces can report transient
negative values for rx queue.

ss ->
State   Recv-Q Send-Q  Local Address:Port  Peer Address:Port
ESTAB   -6     6       127.0.0.1:45956     127.0.0.1:3333

netstat ->
tcp   4294967290      6 127.0.0.1:37784  127.0.0.1:3333 ESTABLISHED

This is because we dont lock socket while computing
tp->rcv_nxt - tp->copied_seq,
and another CPU can update copied_seq before rcv_next in RX path.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 2 changed files with 11 additions and 3 deletions Side-by-side Diff

... ... @@ -27,7 +27,7 @@
27 27 r->idiag_rqueue = sk->sk_ack_backlog;
28 28 r->idiag_wqueue = sk->sk_max_ack_backlog;
29 29 } else {
30   - r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq;
  30 + r->idiag_rqueue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
31 31 r->idiag_wqueue = tp->write_seq - tp->snd_una;
32 32 }
33 33 if (info != NULL)
... ... @@ -2318,6 +2318,7 @@
2318 2318 __be32 src = inet->inet_rcv_saddr;
2319 2319 __u16 destp = ntohs(inet->inet_dport);
2320 2320 __u16 srcp = ntohs(inet->inet_sport);
  2321 + int rx_queue;
2321 2322  
2322 2323 if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
2323 2324 timer_active = 1;
2324 2325  
... ... @@ -2333,12 +2334,19 @@
2333 2334 timer_expires = jiffies;
2334 2335 }
2335 2336  
  2337 + if (sk->sk_state == TCP_LISTEN)
  2338 + rx_queue = sk->sk_ack_backlog;
  2339 + else
  2340 + /*
  2341 + * because we dont lock socket, we might find a transient negative value
  2342 + */
  2343 + rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
  2344 +
2336 2345 seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
2337 2346 "%08X %5d %8d %lu %d %p %lu %lu %u %u %d%n",
2338 2347 i, src, srcp, dest, destp, sk->sk_state,
2339 2348 tp->write_seq - tp->snd_una,
2340   - sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
2341   - (tp->rcv_nxt - tp->copied_seq),
  2349 + rx_queue,
2342 2350 timer_active,
2343 2351 jiffies_to_clock_t(timer_expires - jiffies),
2344 2352 icsk->icsk_retransmits,