Those counters are exported for raw and udp but not for tcp, though they
are incremented.

An example where it is useful is chasing listen overflow. Listen overflow
are counted as a global counter in LINUX_MIB_LISTENOVERFLOWS accessible
in /proc/net/netstat but there is no way to find related drops in the
information exported for tcp. With this patch it will make possible to
correlate growth of LINUX_MIB_LISTENOVERFLOWS with growth of drops for
a tcp socket.

This patch does it for /proc/net/tcp and /proc/net/tcp6, the drops
counter is being incremented in function like tcp_listendrop() which
would help surface error cases like listen overflow and track them to
the correct socket.

That work has been done for raw sockets (/proc/net/raw and
/proc/net/raw6) by Wang Chen in commit 33c732c36169
("[IPV4]: Add raw drops counter.") and commit a92aa318b4b3
("[IPV6]: Add raw6 drops counter.") and by Eric Dumazet for udp ones
(/proc/net/udp and /proc/net/udp6) in commit cb61cb9b8b5e
("udp: sk_drops handling").

Signed-off-by: Stéphan Gorget <sgor...@fb.com>
Signed-off-by: Jeethu Rao <jee...@fb.com>
Cc: David S. Miller <da...@davemloft.net>
Cc: Alexei Starovoitov <a...@fb.com>
Cc: Eric Dumazet <eduma...@google.com>
Cc: kernel-t...@fb.com
Cc: net...@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 Documentation/networking/proc_net_tcp.txt | 30 ++++++++++++++++--------------
 net/ipv4/tcp_ipv4.c                       |  5 +++--
 net/ipv6/tcp_ipv6.c                       |  7 ++++---
 3 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/Documentation/networking/proc_net_tcp.txt 
b/Documentation/networking/proc_net_tcp.txt
index 4a79209..38bda94 100644
--- a/Documentation/networking/proc_net_tcp.txt
+++ b/Documentation/networking/proc_net_tcp.txt
@@ -24,20 +24,22 @@ up into 3 parts because of the length of the line):
       |        |----------------------> receive-queue
       |-------------------------------> transmit-queue
 
-   1000        0 54165785 4 cd1e6040 25 4 27 3 -1
-    |          |    |     |    |     |  | |  | |--> slow start size threshold, 
-    |          |    |     |    |     |  | |  |      or -1 if the threshold
-    |          |    |     |    |     |  | |  |      is >= 0xFFFF
-    |          |    |     |    |     |  | |  |----> sending congestion window
-    |          |    |     |    |     |  | |-------> (ack.quick<<1)|ack.pingpong
-    |          |    |     |    |     |  |---------> Predicted tick of soft 
clock
-    |          |    |     |    |     |              (delayed ACK control data)
-    |          |    |     |    |     |------------> retransmit timeout
-    |          |    |     |    |------------------> location of socket in 
memory
-    |          |    |     |-----------------------> socket reference count
-    |          |    |-----------------------------> inode
-    |          |----------------------------------> unanswered 0-window probes
-    |---------------------------------------------> uid
+   1000        0 54165785 4 cd1e6040 25 4 27 3 -1 0
+    |          |    |     |    |     |  | |  | |  |--> number of drops
+    |          |    |     |    |     |  | |  | |-----> slow start size
+    |          |    |     |    |     |  | |  |         threshold, or -1 if the
+    |          |    |     |    |     |  | |  |         threshold is >= 0xFFFF
+    |          |    |     |    |     |  | |  |-------> sending congestion 
window
+    |          |    |     |    |     |  | |----------> (ack.quick<<1) |
+    |          |    |     |    |     |  |               ack.pingpong
+    |          |    |     |    |     |  |------------> Predicted tick of soft 
clock
+    |          |    |     |    |     |                 (delayed ACK control 
data)
+    |          |    |     |    |     |---------------> retransmit timeout
+    |          |    |     |    |---------------------> location of socket in 
memory
+    |          |    |     |--------------------------> socket reference count
+    |          |    |--------------------------------> inode
+    |          |-------------------------------------> unanswered 0-window 
probes
+    |------------------------------------------------> uid
 
 timer_active:
   0  no timer is pending
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 5af8b80..173e20a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2255,7 +2255,7 @@ static void get_tcp4_sock(struct sock *sk, struct 
seq_file *f, int i)
                rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
 
        seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
-                       "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d",
+                       "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d %d",
                i, src, srcp, dest, destp, state,
                tp->write_seq - tp->snd_una,
                rx_queue,
@@ -2272,7 +2272,8 @@ static void get_tcp4_sock(struct sock *sk, struct 
seq_file *f, int i)
                tp->snd_cwnd,
                state == TCP_LISTEN ?
                    fastopenq->max_qlen :
-                   (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh));
+                   (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh),
+               state == TCP_LISTEN ? atomic_read(&sk->sk_drops) : 0);
 }
 
 static void get_timewait4_sock(const struct inet_timewait_sock *tw,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index d79a1af..1cd296a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1795,8 +1795,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct 
sock *sp, int i)
                rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
 
        seq_printf(seq,
-                  "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-                  "%02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %lu %lu 
%u %u %d\n",
+                  "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X %02X "
+                  "%08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %lu %lu %u %u 
%d %d\n",
                   i,
                   src->s6_addr32[0], src->s6_addr32[1],
                   src->s6_addr32[2], src->s6_addr32[3], srcp,
@@ -1818,7 +1818,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct 
sock *sp, int i)
                   tp->snd_cwnd,
                   state == TCP_LISTEN ?
                        fastopenq->max_qlen :
-                       (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh)
+                       (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh),
+                  state == TCP_LISTEN ? atomic_read(&sp->sk_drops) : 0
                   );
 }
 
-- 
2.9.5

Reply via email to