+ * Federico D. Sacerdoti: Added TCP health monitoring.
Please don't do this.
The kernel community no longer maintains a list of contributors
in the comments. The history is maintained in the git commit log.
thanks for the proof-reading, to Randy Dunlap too. now I have tested the
patch against mainline.
so, anyone has a comment on my actual question about the need for a read-lock?
currently my patch looks like this (again comments are welcome):
diff -rub A/include/linux/tcp.h B/include/linux/tcp.h
@@ -472,6 +474,15 @@*containsrelatedtcp_cookie_transactionsfields.*/structtcp_cookie_values*cookie_values;++/*+*TCPhealthmonitoringcounters.+*/+__u32dup_acks_sent;+__u32dup_pkts_recv;+__u32acks_sent;+__u32pkts_recv;+__u32last_ack_sent;/* Sequence number of the last ack we sent. */};staticinlinestructtcp_sock*tcp_sk(conststructsock*sk)
@@ -4414,6 +4415,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,&tp->out_of_order_queue);__kfree_skb(skb);
@@ -4664,6 +4667,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(sock_net(sk), LINUX_MIB_DELAYEDACKLOST);
@@ -5375,6 +5382,13 @@ tp->rx_opt.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_prediction is to be made * 'S' will always be tp->tcp_header_len >> 2
@@ -2533,6 +2533,82 @@return0;}++/*+*Output/proc/net/tcphealth+*/+#define LINESZ 128++inttcp_health_seq_show(structseq_file*seq,void*v)+{+intlen,num;+charsrcIP[32],destIP[32];++unsignedlongSmoothedRttEstimate,+AcksSent,DupAcksSent,PktsRecv,DupPktsRecv;+structtcp_iter_state*st;++if(v==SEQ_START_TOKEN){+seq_printf(seq,+"TCP Health Monitoring (established connections only)\n"+" -Duplicate ACKs indicate lost or reordered packets on the
@@ -2754,8 +2755,15 @@skb_reserve(buff,MAX_TCP_HEADER);tcp_init_nondata_skb(buff,tcp_acceptable_seq(sk),TCPHDR_ACK);+/* If the rcv_nxt has not advanced since sending our last ACK, this is a
duplicate. */
+ if (tcp_sk(sk)->rcv_nxt == tcp_sk(sk)->last_ack_sent)
+ tcp_sk(sk)->dup_acks_sent++;
+ /* Record the total number of acks sent on this connection. */
+ tcp_sk(sk)->acks_sent++;
+
/* Send it off, this clears delayed acks for us. */
TCP_SKB_CB(buff)->when = tcp_time_stamp;
+ tcp_sk(sk)->last_ack_sent = tcp_sk(sk)->rcv_nxt;
tcp_transmit_skb(sk, buff, 0, GFP_ATOMIC);
}
From: Stephen Hemminger <hidden> Date: 2012-07-13 23:56:05
I am not sure if the is really necessary since the most
of the stats are available elsewhere.
Here are some comments on getting the simplified to match
the kernel style.
}
if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
+ /* Course retransmit inefficiency- this packet has been received twice. */
+ tp->dup_pkts_recv++;
I don't understand that comment, could you use a better sentence please?
tp->rx_opt.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++;
+
Comment seems bigger justification than necessary for simple
operation.
+
+ unsigned long SmoothedRttEstimate,
+ AcksSent, DupAcksSent, PktsRecv, DupPktsRecv;
Do not use CamelCase in kernel code.
+ struct tcp_iter_state *st;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq,
+ "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 "
Header seems excessive, just put one line of header please.
+ "DupAcksSent PktsRecv DupPktsRecv\n");
+ goto out;
+ }
+
+ /* Loop through established TCP connections */
+ st = seq->private;
+
+
+ if (st->state == TCP_SEQ_STATE_ESTABLISHED)
+ {
+/* ; //insert read-lock here */
From: Piotr Sawuk <hidden> Date: 2012-07-16 11:33:23
On Sa, 14.07.2012, 01:55, Stephen Hemminger wrote:
I am not sure if the is really necessary since the most
of the stats are available elsewhere.
if by "most" you mean address and port then you're right.
but even the rtt reported by "ss -i" seems to differ from tcphealth.
however, if instead by "elsewhere" you mean "on the server"...
quoted
+ seq_printf(seq,
+ "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 "
Header seems excessive, just put one line of header please.
I guess the header was sort of documentation for this patch.
I've put it into Kconfig instead.
quoted
+ "DupAcksSent PktsRecv DupPktsRecv\n");
+ goto out;
+ }
+
+ /* Loop through established TCP connections */
+ st = seq->private;
+
+
+ if (st->state == TCP_SEQ_STATE_ESTABLISHED)
+ {
+/* ; //insert read-lock here */
Don't think you need read-lock
you mean I wont get segfault reading a tcp_sock that's gone?
Kernel has %pI4 to print IP addresses.
thanks, I didn't know.
quoted
+ seq_printf(seq, "%*s\n", LINESZ - 1 - len, "");
This padding of line is bogus, just print variable length line.
Are you trying to make it fixed length record file?
I guess so, /proc/net/tcp is doing the same.
wont question the authors of that user-interface.
OK, new version, this time with Kconfig changed:
diff -rub A/include/linux/tcp.h B/include/linux/tcp.h
@@ -492,6 +492,17 @@*containsrelatedtcp_cookie_transactionsfields.*/structtcp_cookie_values*cookie_values;++#ifdef CONFIG_TCPHEALTH+/*+*TCPhealthmonitoringcounters.+*/+__u32dup_acks_sent;+__u32dup_pkts_recv;+__u32acks_sent;+__u32pkts_recv;+__u32last_ack_sent;/* Sequence number of the last ack we sent. */+#endif};staticinlinestructtcp_sock*tcp_sk(conststructsock*sk)
Only in B/include/linux: tcp.h.orig
diff -rub A/net/ipv4/Kconfig B/net/ipv4/Kconfig
@@ -4824,6 +4829,12 @@return;}+#ifdef CONFIG_TCPHEALTH+/* 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++;
+#endif
+
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(sock_net(sk), LINUX_MIB_DELAYEDACKLOST);
@@ -5535,6 +5546,12 @@ tp->rx_opt.saw_tstamp = 0;+#ifdef CONFIG_TCPHEALTH+ /*+ * total per-connection packet arrivals.+ */+ tp->pkts_recv++;+#endif /* pred_flags is 0xS?10 << 16 + snd_wnd * if header_prediction is to be made * 'S' will always be tp->tcp_header_len >> 2
@@ -2772,8 +2772,19 @@skb_reserve(buff,MAX_TCP_HEADER);tcp_init_nondata_skb(buff,tcp_acceptable_seq(sk),TCPHDR_ACK);+#ifdef CONFIG_TCPHEALTH+/* If the rcv_nxt has not advanced since sending our last ACK, this is a
duplicate. */
+ if (tcp_sk(sk)->rcv_nxt == tcp_sk(sk)->last_ack_sent)
+ tcp_sk(sk)->dup_acks_sent++;
+ /* Record the total number of acks sent on this connection. */
+ tcp_sk(sk)->acks_sent++;
+#endif
+
/* Send it off, this clears delayed acks for us. */
TCP_SKB_CB(buff)->when = tcp_time_stamp;
+#ifdef CONFIG_TCPHEALTH
+ tcp_sk(sk)->last_ack_sent = tcp_sk(sk)->rcv_nxt;
+#endif
tcp_transmit_skb(sk, buff, 0, GFP_ATOMIC);
}
From: Piotr Sawuk <hidden> Date: 2012-07-16 13:03:31
On Mo, 16.07.2012, 13:46, Eric Dumazet wrote:
On Mon, 2012-07-16 at 13:33 +0200, Piotr Sawuk wrote:
quoted
On Sa, 14.07.2012, 01:55, Stephen Hemminger wrote:
quoted
I am not sure if the is really necessary since the most
of the stats are available elsewhere.
if by "most" you mean address and port then you're right.
but even the rtt reported by "ss -i" seems to differ from tcphealth.
Thats because tcphealth is wrong, it assumes HZ=1000 ?
tp->srtt unit is jiffies, not ms.
thanks. any conversion-functions in the kernel for that?
tcphealth is a gross hack.
what would you do if you tried making it less gross?
I've not found any similar functionality, in the kernel.
I want to know an estimate for the percentage of data lost in tcp.
and I want to know that without actually sending much packets.
afterall I'm on the receiving end most of the time.
percentage of duplicate packets received is nice too.
you have any suggestions?
On Mon, Jul 16, 2012 at 6:03 AM, Piotr Sawuk [off-list ref] wrote:
On Mo, 16.07.2012, 13:46, Eric Dumazet wrote:
quoted
On Mon, 2012-07-16 at 13:33 +0200, Piotr Sawuk wrote:
quoted
On Sa, 14.07.2012, 01:55, Stephen Hemminger wrote:
quoted
I am not sure if the is really necessary since the most
of the stats are available elsewhere.
if by "most" you mean address and port then you're right.
but even the rtt reported by "ss -i" seems to differ from tcphealth.
Thats because tcphealth is wrong, it assumes HZ=1000 ?
tp->srtt unit is jiffies, not ms.
thanks. any conversion-functions in the kernel for that?
quoted
tcphealth is a gross hack.
what would you do if you tried making it less gross?
I've not found any similar functionality, in the kernel.
I want to know an estimate for the percentage of data lost in tcp.
and I want to know that without actually sending much packets.
afterall I'm on the receiving end most of the time.
percentage of duplicate packets received is nice too.
you have any suggestions?
counting dupack may not be as reliable as you'd like.
say the remote sends you 100 packets and only the first one is lost,
you'll see 99 dupacks. Morover any small degree reordering (<3)
will generate substantial dupacks but the network is perfectly fine
(see Craig Patridge's "reordering is not pathological" paper).
unfortunately receiver can't and does not have to distinguish loss
or reordering. you can infer that but it should not be kernel's job.
there are public tools that inspect tcpdump traces to do that
exposing duplicate packets received can be done via getsockopt(TCP_INFO)
although I don't know what that gives you. the remote can be too
aggressive in retransmission (not just because of a bad RTO) or
the network RTT fluctuates.
I don't what if tracking last_ack_sent (the latest RCV.NXT) without
knowing the ISN is useful.
btw the term project paper cited concludes SACK is not useful is simply
wrong. This makes me suspicious about how rigorous and thoughtful of
its design.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Piotr Sawuk <hidden> Date: 2012-07-21 10:34:40
On Fr, 20.07.2012, 16:06, Yuchung Cheng wrote:
On Mon, Jul 16, 2012 at 6:03 AM, Piotr Sawuk [off-list ref]
wrote:
quoted
On Mo, 16.07.2012, 13:46, Eric Dumazet wrote:
quoted
On Mon, 2012-07-16 at 13:33 +0200, Piotr Sawuk wrote:
quoted
On Sa, 14.07.2012, 01:55, Stephen Hemminger wrote:
quoted
I am not sure if the is really necessary since the most
of the stats are available elsewhere.
if by "most" you mean address and port then you're right.
but even the rtt reported by "ss -i" seems to differ from tcphealth.
Thats because tcphealth is wrong, it assumes HZ=1000 ?
tp->srtt unit is jiffies, not ms.
thanks. any conversion-functions in the kernel for that?
quoted
tcphealth is a gross hack.
what would you do if you tried making it less gross?
I've not found any similar functionality, in the kernel.
I want to know an estimate for the percentage of data lost in tcp.
and I want to know that without actually sending much packets.
afterall I'm on the receiving end most of the time.
percentage of duplicate packets received is nice too.
you have any suggestions?
counting dupack may not be as reliable as you'd like.
say the remote sends you 100 packets and only the first one is lost,
you'll see 99 dupacks. Morover any small degree reordering (<3)
will generate substantial dupacks but the network is perfectly fine
I understand that.
but you must consider the difference between network-health and tcp-health.
network-health on my end I can see by looking at wlan-signal strength.
slow downloads can have many causes, some loose cable is only one possibility.
for example I once played a lan-game, 2 computers connected directly.
however, one computer was 10 times slower than the other.
so when the slow computer would act as server, the game would never start.
the reason wasn't bad connection, it was packet-loss caused by slowness.
and it had to do with the protocol being used (i.e. not tcp).
so when in tcp I get high percentage of dupack I see something's wrong.
not necessarily with the physical connection, but with protocol-handling.
the paper showed dupacks indicate spikes in network-usage.
and as we all know the bottleneck isn't the cable, it's data-processing.
when there is a spike, lots of users connecting, network itself is ok.
however, reordering and lost packets indicate something's up with the server.
and that's actually the info I'm after.
if I were the net-admin I would be interested in network-health too.
bad connection indicated by packet-loss itself means I've got to check cables.
but a user might have much wider area of interest.
the user can't do anything about the cables, but yet is interested in them.
i.e. useless info for the net-admin could be interesting for the user.
that's why I do not recommend tcphealth for servers, useless overhead.
so, if you want to judge usefulness of this patch, consider the situation:
you are powerless but interested in responsiveness of thousands of servers.
you want to learn how those servers behave at different times of a day.
isn't dupacks and dup-packets the best info on that you can possibly get?
(see Craig Patridge's "reordering is not pathological" paper).
thanks, will look into that.
unfortunately receiver can't and does not have to distinguish loss
true, not needed for the protocol.
on a higher level it sill can be interesting though.
most of the work for preventing packetloss must be done by the sender.
but as I said before, the receiver can do something too: avoid traffic-jams!
in a network many things are predictable, can be reprogrammed.
this way a network could become more efficient as a whole.
that's what spikes my interest in tcphealth, thinking more globally.
or reordering. you can infer that but it should not be kernel's job.
that's why I made it an option as opposed to what the original author did.
theoretically it should be possible to get the same functionality without it.
just read the raw network-data and emulate the work of tcp and tcphealth.
but that definitely would add a big overhead as tcp-handling is duplicated.
there are public tools that inspect tcpdump traces to do that
good example. so to figure out dupacks you filter out the acks.
and you must somehow compare them, or you parse them the way the kernel does.
in the latter case you'll have to recreate the kernel's internal data.
definitely faster, but could result in duplicate code, that requires space.
also you should consider that not all users have privilegues for tcpdump.
and if they had, it would add another security-risk to their computer.
and you'd have to consider multiple users on one computer, using that service.
I can imagine a daemon in the background doing what tcphealth does.
that's the alternative, allows for more fine-grained security.
it could disallow spying on what connections other users have.
(of course then you'd need to remove /proc/net/tcp output too.)
but imagine the nightmare of keeping that daemon secure.
afterall it must be privilegued to read all network data.
if the kernel would provide what I'm looking for, this daemon could still run.
but then it wouldn't need that risky privilegues, could focus on other stuff.
the task of preventing users from seeing eachothers connections is enough...
exposing duplicate packets received can be done via getsockopt(TCP_INFO)
although I don't know what that gives you. the remote can be too
aggressive in retransmission (not just because of a bad RTO) or
the network RTT fluctuates.
TCP_INFO contains only duplicate packets *sent* (retransmits), not received!
am I missing something? can you give a code-example that can obtain such info?
if running that code in userspace results in same values as tcphealth...
well, actually dupacks is more interesting than dup-packets.
afterall in usual usage the latter will always be zero.
I don't what if tracking last_ack_sent (the latest RCV.NXT) without
knowing the ISN is useful.
so you suggest I should store and compare ISN too, for accuracy?
you think the gain in accuracy justifies the added overhead?
btw the term project paper cited concludes SACK is not useful is simply
wrong. This makes me suspicious about how rigorous and thoughtful of
its design.
isn't my paper.
but I'd guess the usefulness of SACK is only doubted from pov of users.
remember, users connect to many servers.
if a server behaves badly, choose another one.
servers do not have such a choice, for them SACK naturally is important.
a server would just need to look at TCP_INFO to see how useful SACK is.
so I would conclude the author was quite thoughtful about users' pov.
(and quite ignorant about the servers.)
no matter how little knowledge the authors have, tcphealth is interesting.
maybe it was a random discovery by sheer luck.
the correlation between the data it provides and reality is compelling.
if we'd judge inventions by the stupidity of their inventors...