aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2013-04-18 02:52:51 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-18 14:57:25 -0400
commit0e280af026a5662ffd57c4e623b822df1f7f47ff (patch)
treeee3fa2a5523223f8ff079b075dc4e1959ed0c0f5
parent5a5967d80423e859036972986b3711458f2cd385 (diff)
tcp: introduce TCPSpuriousRtxHostQueues SNMP counter
Host queues (Qdisc + NIC) can hold packets so long that TCP can eventually retransmit a packet before the first transmit even left the host. Its not clear right now if we could avoid this in the first place : - We could arm RTO timer not at the time we enqueue packets, but at the time we TX complete them (tcp_wfree()) - Cancel the sending of the new copy of the packet if prior one is still in queue. This patch adds instrumentation so that we can at least see how often this problem happens. TCPSpuriousRtxHostQueues SNMP counter is incremented every time we detect the fast clone is not yet freed in tcp_transmit_skb() Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Yuchung Cheng <ycheng@google.com> Cc: Neal Cardwell <ncardwell@google.com> Cc: Tom Herbert <therbert@google.com> Cc: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/uapi/linux/snmp.h1
-rw-r--r--net/ipv4/proc.c1
-rw-r--r--net/ipv4/tcp_output.c7
3 files changed, 9 insertions, 0 deletions
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index e00013a1debc..fefdec91c68b 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -247,6 +247,7 @@ enum
247 LINUX_MIB_TCPFASTOPENPASSIVEFAIL, /* TCPFastOpenPassiveFail */ 247 LINUX_MIB_TCPFASTOPENPASSIVEFAIL, /* TCPFastOpenPassiveFail */
248 LINUX_MIB_TCPFASTOPENLISTENOVERFLOW, /* TCPFastOpenListenOverflow */ 248 LINUX_MIB_TCPFASTOPENLISTENOVERFLOW, /* TCPFastOpenListenOverflow */
249 LINUX_MIB_TCPFASTOPENCOOKIEREQD, /* TCPFastOpenCookieReqd */ 249 LINUX_MIB_TCPFASTOPENCOOKIEREQD, /* TCPFastOpenCookieReqd */
250 LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES, /* TCPSpuriousRtxHostQueues */
250 __LINUX_MIB_MAX 251 __LINUX_MIB_MAX
251}; 252};
252 253
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index b6f2ea174898..6da51d55d03a 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -269,6 +269,7 @@ static const struct snmp_mib snmp4_net_list[] = {
269 SNMP_MIB_ITEM("TCPFastOpenPassiveFail", LINUX_MIB_TCPFASTOPENPASSIVEFAIL), 269 SNMP_MIB_ITEM("TCPFastOpenPassiveFail", LINUX_MIB_TCPFASTOPENPASSIVEFAIL),
270 SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), 270 SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW),
271 SNMP_MIB_ITEM("TCPFastOpenCookieReqd", LINUX_MIB_TCPFASTOPENCOOKIEREQD), 271 SNMP_MIB_ITEM("TCPFastOpenCookieReqd", LINUX_MIB_TCPFASTOPENCOOKIEREQD),
272 SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues", LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES),
272 SNMP_MIB_SENTINEL 273 SNMP_MIB_SENTINEL
273}; 274};
274 275
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index d12694353540..5f28131eb37e 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -846,6 +846,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
846 __net_timestamp(skb); 846 __net_timestamp(skb);
847 847
848 if (likely(clone_it)) { 848 if (likely(clone_it)) {
849 const struct sk_buff *fclone = skb + 1;
850
851 if (unlikely(skb->fclone == SKB_FCLONE_ORIG &&
852 fclone->fclone == SKB_FCLONE_CLONE))
853 NET_INC_STATS_BH(sock_net(sk),
854 LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES);
855
849 if (unlikely(skb_cloned(skb))) 856 if (unlikely(skb_cloned(skb)))
850 skb = pskb_copy(skb, gfp_mask); 857 skb = pskb_copy(skb, gfp_mask);
851 else 858 else