I would like to submit a patch that adds a /proc file to the kernel which
monitors the health of active TCP connections. It does this by counting
the number of duplicate ACKs sent out, among other things.
I have a website detailing the exact metrics used and why I choose them:
http://heron.ucsd.edu/tcphealth/
I have tested this patch on 5 i686 computers, and have had many downloads of it
by users interested in my tcphealth gkrellm monitoring module. Since I am forced
to update my patch often due to demand, I would like to formally submit
it to you for inclusion in the new 2.5 development kernel.
Sincerely,
Federico Sacerdoti
Here is the patch for the 2.5.1 kernel. It also works for kernel 2.5.2pre11.
----------- Start Patch ------------
diff -Naur pristine-linux-2.5.1/include/net/sock.h linux-2.5.1/include/net/sock.h
--- pristine-linux-2.5.1/include/net/sock.h Mon Jan 14 13:43:41 2002
+++ linux-2.5.1/include/net/sock.h Mon Jan 14 13:48:49 2002
@@ -24,6 +24,7 @@
* Alan Cox : Eliminate low level recv/recvfrom
* David S. Miller : New socket lookup architecture.
* Steve Whitehouse: Default routines for sock_ops
+ * Federico D. Sacerdoti : Added TCP health counters.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -278,6 +279,7 @@
__u32 lrcvtime; /* timestamp of last received data packet*/
__u16 last_seg_size; /* Size of last incoming segment */
__u16 rcv_mss; /* MSS used for delayed ACK decisions */
+ __u32 last_ack_sent; /* Sequence number of the last ack we sent. */
} ack;
/* Data for direct copy to user */
@@ -418,6 +420,14 @@
int linger2;
unsigned long last_synq_overflow;
+
+ /*
+ * TCP health monitoring counters.
+ */
+ __u32 dup_acks_sent;
+ __u32 dup_pkts_recv;
+ __u32 acks_sent;
+ __u32 pkts_recv;
};
diff -Naur pristine-linux-2.5.1/net/ipv4/af_inet.c linux-2.5.1/net/ipv4/af_inet.c
--- pristine-linux-2.5.1/net/ipv4/af_inet.c Mon Jan 14 13:43:45 2002
+++ linux-2.5.1/net/ipv4/af_inet.c Mon Jan 14 13:53:14 2002
@@ -56,6 +56,7 @@
* Some other random speedups.
* Cyrus Durgin : Cleaned up file for kmod hacks.
* Andi Kleen : Fix inet_stream_connect TCP race.
+ * Federico D. Sacerdoti : Added tcphealth /proc/net file.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -129,6 +130,7 @@
extern int afinet_get_info(char *, char **, off_t, int);
extern int tcp_get_info(char *, char **, off_t, int);
extern int udp_get_info(char *, char **, off_t, int);
+extern int tcp_health_get_info(char *, char **, off_t, int);
extern void ip_mc_drop_socket(struct sock *sk);
#ifdef CONFIG_DLCI
@@ -1196,6 +1198,7 @@
proc_net_create ("sockstat", 0, afinet_get_info);
proc_net_create ("tcp", 0, tcp_get_info);
proc_net_create ("udp", 0, udp_get_info);
+ proc_net_create ("tcphealth", 0, tcp_health_get_info);
#endif /* CONFIG_PROC_FS */
return 0;
}
diff -Naur pristine-linux-2.5.1/net/ipv4/proc.c linux-2.5.1/net/ipv4/proc.c
--- pristine-linux-2.5.1/net/ipv4/proc.c Mon Jan 14 13:43:45 2002
+++ linux-2.5.1/net/ipv4/proc.c Mon Jan 14 14:02:57 2002
@@ -26,6 +26,7 @@
* Andi Kleen : Add support for open_requests and
* split functions for more readibility.
* Andi Kleen : Add support for /proc/net/netstat
+ * Federico D. Sacerdoti : Added support for /proc/net/tcphealth
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -212,3 +213,97 @@
len = 0;
return len;
}
+
+/*
+ * Output /proc/net/tcphealth
+ */
+#define LINESZ 128
+
+int tcp_health_get_info(char *buffer, char **start, off_t offset, int length)
+{
+ int len=0, i=0, num=0;
+ off_t pos=0, begin=0;
+ char tmpbuf[LINESZ+1], srcIP[32], destIP[32];
+
+ unsigned long dest, src, SmoothedRttEstimate,
+ AcksSent, DupAcksSent, PktsRecv, DupPktsRecv;
+ unsigned short destp, srcp;
+
+ len = sprintf(buffer,
+ "TCP Health Monitoring (established connections only)\n"
+ " -Duplicate ACKs indicate lost or reordered packets on the connection.\n"
+ " -Duplicate Packets Received signal a slow and badly inefficient connection.\n"
+ " -RttEst estimates how long future packets will take on a round trip over the connection.\n"
+ "id Local Address Remote Address RttEst(ms) AcksSent "
+ "DupAcksSent PktsRecv DupPktsRecv\n");
+ pos=len;
+
+ /* Loop through established TCP connections */
+ local_bh_disable();
+ for (i=0; i < tcp_ehash_size; i++) {
+ struct tcp_ehash_bucket *head = &tcp_ehash[i];
+ struct sock *sk;
+ struct tcp_opt *tp;
+
+ read_lock(&head->lock);
+ for (sk=head->chain; sk; sk=sk->next) {
+ if (!TCP_INET_FAMILY(sk->family))
+ continue;
+ pos+=LINESZ;
+ if (pos <= offset)
+ continue;
+
+ dest = ntohl(sk->daddr);
+ src = ntohl(sk->rcv_saddr);
+ destp = ntohs(sk->dport);
+ srcp = ntohs(sk->sport);
+
+ tp = &(sk->tp_pinfo.af_tcp);
+ SmoothedRttEstimate = (tp->srtt >> 3);
+ AcksSent = tp->acks_sent;
+ DupAcksSent = tp->dup_acks_sent;
+ PktsRecv = tp->pkts_recv;
+ DupPktsRecv = tp->dup_pkts_recv;
+
+ sprintf(srcIP, "%lu.%lu.%lu.%lu:%u",
+ ((src >> 24) & 0xFF), ((src >> 16) & 0xFF), ((src >> 8) & 0xFF), (src & 0xFF),
+ srcp);
+ sprintf(destIP, "%lu.%lu.%lu.%lu:%u",
+ ((dest >> 24) & 0xFF), ((dest >> 16) & 0xFF), ((dest >> 8) & 0xFF), (dest & 0xFF),
+ destp);
+
+ sprintf(tmpbuf, "%d: %-21s %-21s "
+ "%8lu %8lu %8lu %8lu %8lu",
+ num,
+ srcIP,
+ destIP,
+ SmoothedRttEstimate,
+ AcksSent,
+ DupAcksSent,
+ PktsRecv,
+ DupPktsRecv
+ );
+
+ len += sprintf(buffer+len, "%-*s\n", LINESZ-1, tmpbuf);
+ if(pos >= offset+length) {
+ read_unlock(&head->lock);
+ goto out;
+ }
+ num++;
+ }
+ read_unlock(&head->lock);
+ }
+
+out:
+ local_bh_enable();
+
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if(len>length)
+ len = length;
+ if (len<0)
+ len = 0;
+ return len;
+}
+
diff -Naur pristine-linux-2.5.1/net/ipv4/tcp_input.c linux-2.5.1/net/ipv4/tcp_input.c
--- pristine-linux-2.5.1/net/ipv4/tcp_input.c Mon Jan 14 13:43:45 2002
+++ linux-2.5.1/net/ipv4/tcp_input.c Mon Jan 14 14:12:57 2002
@@ -60,6 +60,7 @@
* Pasi Sarolahti,
* Panu Kuhlberg: Experimental audit of TCP (re)transmission
* engine. Lots of bugs are found.
+ * Federico D. Sacerdoti: Added TCP health monitoring.
*/
#include <linux/config.h>
@@ -2496,6 +2497,8 @@
}
if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
+ /* Course retransmit inefficiency- this packet has been received twice. */
+ tp->dup_pkts_recv++;
SOCK_DEBUG(sk, "ofo packet was already received \n");
__skb_unlink(skb, skb->list);
__kfree_skb(skb);
@@ -2608,6 +2611,10 @@
return;
}
+ /* A packet is a "duplicate" if it contains bytes we have already received. */
+ if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
+ tp->dup_pkts_recv++;
+
if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
/* A retransmit, 2nd most common case. Force an immediate ack. */
NET_INC_STATS_BH(DelayedACKLost);
@@ -3241,6 +3248,14 @@
*/
tp->saw_tstamp = 0;
+
+ /*
+ * Tcp health monitoring is interested in
+ * total per-connection packet arrivals.
+ * This is in the fast path, but is quick.
+ */
+
+ tp->pkts_recv++;
/* pred_flags is 0xS?10 << 16 + snd_wnd
* if header_predition is to be made
diff -Naur pristine-linux-2.5.1/net/ipv4/tcp_output.c linux-2.5.1/net/ipv4/tcp_output.c
--- pristine-linux-2.5.1/net/ipv4/tcp_output.c Mon Jan 14 13:43:45 2002
+++ linux-2.5.1/net/ipv4/tcp_output.c Mon Jan 14 14:16:49 2002
@@ -33,6 +33,7 @@
* Andrea Arcangeli: SYNACK carry ts_recent in tsecr.
* Cacophonix Gaul : draft-minshall-nagle-01
* J Hadi Salim : ECN support
+ * Federico D. Sacerdoti : Added TCP health monitoring.
*
*/
@@ -1321,9 +1322,16 @@
TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
TCP_SKB_CB(buff)->sacked = 0;
+ /* If the rcv_nxt has not advanced since sending our last ACK, this is a duplicate. */
+ if (tp->rcv_nxt == tp->ack.last_ack_sent)
+ tp->dup_acks_sent++;
+ /* Record the total number of acks sent on this connection. */
+ tp->acks_sent++;
+
/* Send it off, this clears delayed acks for us. */
TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
TCP_SKB_CB(buff)->when = tcp_time_stamp;
+ tp->ack.last_ack_sent = tp->rcv_nxt;
tcp_transmit_skb(sk, buff);
}
}
-------------- End Patch -------------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/