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
This commit is contained in:
parent
5b40c0aa73
commit
a36230f75e
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7593,14 +7593,12 @@ bbr_log_ack(struct tcpcb *tp, struct tcpopt *to, struct tcphdr *th,
|
||||
}
|
||||
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)
|
||||
|
@ -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 @@ rack_note_dsack(struct tcp_rack *rack, tcp_seq start, tcp_seq end)
|
||||
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) {
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
@ -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} "
|
||||
|
Loading…
Reference in New Issue
Block a user