git: a36230f75e0a - main - tcp: Make dsack stats available in netstat and also make sure its aware of TLP's.

Randall Stewart rrs at FreeBSD.org
Fri Oct 1 14:36:39 UTC 2021


The branch main has been updated by rrs:

URL: https://cgit.FreeBSD.org/src/commit/?id=a36230f75e0ae5090e4ef47393536255b436cca6

commit a36230f75e0ae5090e4ef47393536255b436cca6
Author:     Randall Stewart <rrs at FreeBSD.org>
AuthorDate: 2021-10-01 14:32:30 +0000
Commit:     Randall Stewart <rrs at FreeBSD.org>
CommitDate: 2021-10-01 14:36:27 +0000

    tcp: Make dsack stats available in netstat and also make sure its aware of TLP's.
    
    DSACK accounting has been for quite some time under a NETFLIX_STATS ifdef. Statistics
    on DSACKs however are very useful in figuring out how much bad retransmissions you
    are doing. This is further complicated, however, by stacks that do TLP. A TLP
    when discovering a lost ack in the reverse path will cause the generation
    of a DSACK. For this situation we introduce a new dsack-tlp-bytes as well
    as the more traditional dsack-bytes and dsack-packets. These will now
    all display in netstat -p tcp -s. This also updates all stacks that
    are currently built to keep track of these stats.
    
    Reviewed by: tuexen
    Sponsored by: Netflix Inc.
    Differential Revision: https://reviews.freebsd.org/D32158
---
 sys/netinet/tcp_sack.c        |  6 ++++++
 sys/netinet/tcp_stacks/bbr.c  |  4 +---
 sys/netinet/tcp_stacks/rack.c | 14 +++++++++-----
 sys/netinet/tcp_subr.c        | 27 +++++++++++++++++++++++++++
 sys/netinet/tcp_var.h         | 16 ++++++++++++++--
 usr.bin/netstat/inet.c        |  6 ++++++
 6 files changed, 63 insertions(+), 10 deletions(-)

diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c
index 9753536926d5..25eb633fbbd4 100644
--- a/sys/netinet/tcp_sack.c
+++ b/sys/netinet/tcp_sack.c
@@ -604,6 +604,12 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
 			    SEQ_GT(sack.end, tp->snd_una) &&
 			    SEQ_LEQ(sack.end, tp->snd_max)) {
 				sack_blocks[num_sack_blks++] = sack;
+			} else if (SEQ_LEQ(sack.start, th_ack) &&
+			    SEQ_LEQ(sack.end, th_ack)) {
+				/*
+				 * Its a D-SACK block.
+				 */
+				tcp_record_dsack(tp, sack.start, sack.end, 0);
 			}
 		}
 	}
diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c
index c96fec07b6c9..3c4cf0f54d97 100644
--- a/sys/netinet/tcp_stacks/bbr.c
+++ b/sys/netinet/tcp_stacks/bbr.c
@@ -7593,14 +7593,12 @@ proc_sack:
 			}
 			sack_blocks[num_sack_blks] = sack;
 			num_sack_blks++;
-#ifdef NETFLIX_STATS
 		} else if (SEQ_LEQ(sack.start, th_ack) &&
 		    SEQ_LEQ(sack.end, th_ack)) {
 			/*
 			 * Its a D-SACK block.
 			 */
-			tcp_record_dsack(sack.start, sack.end);
-#endif
+			tcp_record_dsack(tp, sack.start, sack.end, 0);
 		}
 	}
 	if (num_sack_blks == 0)
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index 2369a1c368bf..00f830caf217 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -9402,11 +9402,12 @@ rack_do_detection(struct tcpcb *tp, struct tcp_rack *rack,  uint32_t bytes_this_
 }
 #endif
 
-static void
+static int
 rack_note_dsack(struct tcp_rack *rack, tcp_seq start, tcp_seq end)
 {
 
 	uint32_t am, l_end;
+	int was_tlp = 0;
 
 	if (SEQ_GT(end, start))
 		am = end - start;
@@ -9422,6 +9423,7 @@ rack_note_dsack(struct tcp_rack *rack, tcp_seq start, tcp_seq end)
 		 * our previous retransmit TLP.
 		 */
 		rack_log_dsack_event(rack, 7, __LINE__, start, end);
+		was_tlp = 1;
 		goto skip_dsack_round;
 	}
 	if (rack->rc_last_sent_tlp_seq_valid) {
@@ -9433,6 +9435,7 @@ rack_note_dsack(struct tcp_rack *rack, tcp_seq start, tcp_seq end)
 			 * for reordering purposes.
 			 */
 			rack_log_dsack_event(rack, 7, __LINE__, start, end);
+			was_tlp = 1;
 			goto skip_dsack_round;
 		}
 	}
@@ -9462,6 +9465,7 @@ skip_dsack_round:
 		rack->r_ctl.retran_during_recovery = 0;
 		rack->r_ctl.dsack_byte_cnt = 0;
 	}
+	return (was_tlp);
 }
 
 static void
@@ -9614,13 +9618,13 @@ rack_log_ack(struct tcpcb *tp, struct tcpopt *to, struct tcphdr *th, int entered
 			num_sack_blks++;
 		} else if (SEQ_LEQ(sack.start, th_ack) &&
 			   SEQ_LEQ(sack.end, th_ack)) {
-#ifdef NETFLIX_STATS
+			int was_tlp;
+
+			was_tlp = rack_note_dsack(rack, sack.start, sack.end);
 			/*
 			 * Its a D-SACK block.
 			 */
-			tcp_record_dsack(sack.start, sack.end);
-#endif
-			rack_note_dsack(rack, sack.start, sack.end);
+			tcp_record_dsack(tp, sack.start, sack.end, was_tlp);
 		}
 	}
 	if (rack->rc_dsack_round_seen) {
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 697ae7d3270b..9d66086a383b 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -390,6 +390,30 @@ static int tcp_fb_cnt = 0;
 struct tcp_funchead t_functions;
 static struct tcp_function_block *tcp_func_set_ptr = &tcp_def_funcblk;
 
+void
+tcp_record_dsack(struct tcpcb *tp, tcp_seq start, tcp_seq end, int tlp)
+{
+	TCPSTAT_INC(tcps_dsack_count);
+	tp->t_dsack_pack++;
+	if (tlp == 0) {
+		if (SEQ_GT(end, start)) {
+			tp->t_dsack_bytes += (end - start);
+			TCPSTAT_ADD(tcps_dsack_bytes, (end - start));
+		} else {
+			tp->t_dsack_tlp_bytes += (start - end);
+			TCPSTAT_ADD(tcps_dsack_bytes, (start - end));
+		}
+	} else {
+		if (SEQ_GT(end, start)) {
+			tp->t_dsack_bytes += (end - start);
+			TCPSTAT_ADD(tcps_dsack_tlp_bytes, (end - start));
+		} else {
+			tp->t_dsack_tlp_bytes += (start - end);
+			TCPSTAT_ADD(tcps_dsack_tlp_bytes, (start - end));
+		}
+	}
+}
+
 static struct tcp_function_block *
 find_tcp_functions_locked(struct tcp_function_set *fs)
 {
@@ -4003,6 +4027,9 @@ tcp_inptoxtp(const struct inpcb *inp, struct xtcpcb *xt)
 		xt->t_snd_wnd = tp->snd_wnd;
 		xt->t_snd_cwnd = tp->snd_cwnd;
 		xt->t_snd_ssthresh = tp->snd_ssthresh;
+		xt->t_dsack_bytes = tp->t_dsack_bytes;
+		xt->t_dsack_tlp_bytes = tp->t_dsack_tlp_bytes;
+		xt->t_dsack_pack = tp->t_dsack_pack;
 		xt->t_maxseg = tp->t_maxseg;
 		xt->xt_ecn = (tp->t_flags2 & TF2_ECN_PERMIT) ? 1 : 0 +
 			     (tp->t_flags2 & TF2_ACE_PERMIT) ? 2 : 0;
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index c26f503f4a1d..d5b2963ef4dc 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -265,6 +265,9 @@ struct tcpcb {
 	uint64_t t_sndtlpbyte;		/* total tail loss probe bytes sent */
 	uint64_t t_sndbytes;		/* total bytes sent */
 	uint64_t t_snd_rxt_bytes;	/* total bytes retransmitted */
+	uint32_t t_dsack_bytes;		/* Total number of dsack bytes we have received */
+	uint32_t t_dsack_tlp_bytes;	/* Total number of dsack bytes we have received for TLPs sent */
+	uint32_t t_dsack_pack;		/* Total dsack packets we have recieved */
 
 	uint8_t t_tfo_client_cookie_len; /* TCP Fast Open client cookie length */
 	uint32_t t_end_info_status;	/* Status flag of end info */
@@ -703,7 +706,12 @@ struct	tcpstat {
 	uint64_t tcps_tunneled_pkts;	/* Packets encap's in UDP received */
 	uint64_t tcps_tunneled_errs;	/* Packets that had errors that were UDP encaped */
 
-	uint64_t _pad[9];		/* 6 UTO, 3 TBD */
+	/* Dsack related stats */
+	uint64_t tcps_dsack_count;	/* Number of ACKs arriving with DSACKs */
+	uint64_t tcps_dsack_bytes;	/* Number of bytes DSACK'ed no TLP */
+	uint64_t tcps_dsack_tlp_bytes;	/* Number of bytes DSACK'ed due to TLPs */
+
+	uint64_t _pad[6];		/* 3 UTO, 3 TBD */
 };
 
 #define	tcps_rcvmemdrop	tcps_rcvreassfull	/* compat */
@@ -801,9 +809,12 @@ struct xtcpcb {
 	uint32_t	t_rcv_wnd;		/* (s) */
 	uint32_t	t_snd_wnd;		/* (s) */
 	uint32_t	xt_ecn;			/* (s) */
+	uint32_t	t_dsack_bytes;		/* (n) */
+	uint32_t	t_dsack_tlp_bytes;	/* (n) */
+	uint32_t	t_dsack_pack;		/* (n) */
 	uint16_t	xt_encaps_port;		/* (s) */
 	int16_t		spare16;
-	int32_t		spare32[25];
+	int32_t		spare32[22];
 } __aligned(8);
 
 #ifdef _KERNEL
@@ -1064,6 +1075,7 @@ int	 tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *,
 	    struct mbuf *, int);
 void	 tcp_setpersist(struct tcpcb *);
 void	 tcp_slowtimo(void);
+void	 tcp_record_dsack(struct tcpcb *tp, tcp_seq start, tcp_seq end, int tlp);
 struct tcptemp *
 	 tcpip_maketemplate(struct inpcb *);
 void	 tcpip_fillheaders(struct inpcb *, uint16_t, void *, void *);
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 45c5f05e60b8..2d3a4bb10d52 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -695,6 +695,12 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
 	    "{N:/window probe%s}\n");
 	p(tcps_rcvwinupd, "\t\t{:receive-window-update-packets/%ju} "
 	    "{N:/window update packet%s}\n");
+	p(tcps_dsack_count, "\t\t{:received-with-dsack-packets/%ju} "
+	    "{N:/packet%s received with dsack}\n");
+	p(tcps_dsack_bytes, "\t\t{:received-with-dsack-bytes/%ju} "
+	    "{N:/dsack byte%s received (no TLP involved)}\n");
+	p(tcps_dsack_tlp_bytes, "\t\t{:received-with-dsack-bytes-tlp/%ju} "
+	    "{N:/dsack byte%s received (TLP responsible)}\n");
 	p(tcps_rcvafterclose, "\t\t{:received-after-close-packets/%ju} "
 	    "{N:/packet%s received after close}\n");
 	p(tcps_rcvbadsum, "\t\t{:discard-bad-checksum/%ju} "


More information about the dev-commits-src-all mailing list