This is a patch which adds instruments to the TCP MTU probing. It breaks netstat -s because it extends the line length of /proc/net/netstat past 1024 characters, so it is not safe to apply. I'm sending it for reference only at this point.
-John
diff --git a/include/linux/snmp.h b/include/linux/snmp.h --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -260,6 +260,12 @@ enum LINUX_MIB_TCPABORTONLINGER, /* TCPAbortOnLinger */ LINUX_MIB_TCPABORTFAILED, /* TCPAbortFailed */ LINUX_MIB_TCPMEMORYPRESSURES, /* TCPMemoryPressures */ + LINUX_MIB_TCPMTUPROBESTALLS, /* TCPMTUProbeStalls */ + LINUX_MIB_TCPMTUPROBEFAILS, /* TCPMTUProbeFails */ + LINUX_MIB_TCPMTUPROBESUCCEEDS, /* TCPMTUProbeSucceeds */ + LINUX_MIB_TCPMTUPROBEINCONCLUSIVES, /* TCPMTUProbeInconclusives */ + LINUX_MIB_TCPMTUBLACKHOLEENABLES, /* TCPMTUBlackholeEnables */ + LINUX_MIB_TCPMTUBLACKHOLEREDUCTIONS, /* TCPMTUBlackholeReductions */ __LINUX_MIB_MAX }; diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -242,6 +242,12 @@ static const struct snmp_mib snmp4_net_l SNMP_MIB_ITEM("TCPAbortOnLinger", LINUX_MIB_TCPABORTONLINGER), SNMP_MIB_ITEM("TCPAbortFailed", LINUX_MIB_TCPABORTFAILED), SNMP_MIB_ITEM("TCPMemoryPressures", LINUX_MIB_TCPMEMORYPRESSURES), + SNMP_MIB_ITEM("TCPMTUProbeStalls", LINUX_MIB_TCPMTUPROBESTALLS), + SNMP_MIB_ITEM("TCPMTUProbeFails", LINUX_MIB_TCPMTUPROBEFAILS), + SNMP_MIB_ITEM("TCPMTUProbeSucceeds", LINUX_MIB_TCPMTUPROBESUCCEEDS), + SNMP_MIB_ITEM("TCPMTUProbeInconclusives", LINUX_MIB_TCPMTUPROBEINCONCLUSIVES), + SNMP_MIB_ITEM("TCPMTUBlackholeEnables", LINUX_MIB_TCPMTUBLACKHOLEENABLES), + SNMP_MIB_ITEM("TCPMTUBlackholeReductions", LINUX_MIB_TCPMTUBLACKHOLEREDUCTIONS), SNMP_MIB_SENTINEL }; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1894,6 +1894,7 @@ static void tcp_mtup_probe_failed(struct { struct inet_connection_sock *icsk = inet_csk(sk); + NET_INC_STATS_BH(LINUX_MIB_TCPMTUPROBEFAILS); icsk->icsk_mtup.search_high = icsk->icsk_mtup.probe_size - 1; icsk->icsk_mtup.probe_size = 0; } @@ -1903,6 +1904,7 @@ static void tcp_mtup_probe_success(struc struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); + NET_INC_STATS_BH(LINUX_MIB_TCPMTUPROBESUCCEEDS); /* FIXME: breaks with very large cwnd */ tp->prior_ssthresh = tcp_current_ssthresh(sk); tp->snd_cwnd = tp->snd_cwnd * diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1270,6 +1270,7 @@ static int tcp_write_xmit(struct sock *s /* Do MTU probing. */ if ((result = tcp_mtu_probe(sk)) == 0) { + NET_INC_STATS_BH(LINUX_MIB_TCPMTUPROBESTALLS); return 0; } else if (result > 0) { sent_pkts = 1; @@ -1651,6 +1652,7 @@ int tcp_retransmit_skb(struct sock *sk, /* Inconslusive MTU probe */ if (icsk->icsk_mtup.probe_size) { + NET_INC_STATS_BH(LINUX_MIB_TCPMTUPROBEINCONCLUSIVES); icsk->icsk_mtup.probe_size = 0; } diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -133,9 +133,11 @@ static int tcp_write_timeout(struct sock /* Black hole detection */ if (sysctl_tcp_mtu_probing) { if (!icsk->icsk_mtup.enabled) { + NET_INC_STATS_BH(LINUX_MIB_TCPMTUBLACKHOLEENABLES); icsk->icsk_mtup.enabled = 1; tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); } else { + NET_INC_STATS_BH(LINUX_MIB_TCPMTUBLACKHOLEREDUCTIONS); mss = min(sysctl_tcp_base_mss, tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low)/2); mss = max(mss, 68 - tp->tcp_header_len);