diff options
author | Richard Scheffenegger <rscheff@FreeBSD.org> | 2020-09-25 10:38:19 +0000 |
---|---|---|
committer | Richard Scheffenegger <rscheff@FreeBSD.org> | 2020-09-25 10:38:19 +0000 |
commit | e39956612370981605b903fd7609dca0db81a65c (patch) | |
tree | f5ec0e7d99f4acc123a8ce6941579e262b576e16 /sys/netinet | |
parent | 1567c937e2cb709355b1cc3b62c8438147d6e05b (diff) | |
download | src-test2-e39956612370981605b903fd7609dca0db81a65c.tar.gz src-test2-e39956612370981605b903fd7609dca0db81a65c.zip |
TCP: send full initial window when timestamps are in use
The fastpath in tcp_output tries to send out
full segments, and avoid sending partial segments by
comparing against the static t_maxseg variable.
That value does not consider tcp options like timestamps,
while the initial window calculation is using
the correct dynamic tcp_maxseg() function.
Due to this interaction, the last, full size segment
is considered too short and not sent out immediately.
Reviewed by: tuexen
MFC after: 2 weeks
Sponsored by: NetApp, Inc.
Differential Revision: https://reviews.freebsd.org/D26478
Notes
Notes:
svn path=/head/; revision=366150
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/tcp.h | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 14 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 13 |
3 files changed, 22 insertions, 7 deletions
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h index 0a5226836f0f..faf142959375 100644 --- a/sys/netinet/tcp.h +++ b/sys/netinet/tcp.h @@ -80,6 +80,8 @@ struct tcphdr { u_short th_urp; /* urgent pointer */ }; +#define PADTCPOLEN(len) ((((len) / 4) + !!((len) % 4)) * 4) + #define TCPOPT_EOL 0 #define TCPOLEN_EOL 1 #define TCPOPT_PAD 0 /* padding after EOL */ diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 2485651df6e7..a7611ceb66f7 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -591,6 +591,20 @@ after_sack_rexmit: if (len >= tp->t_maxseg) goto send; /* + * As the TCP header options are now + * considered when setting up the initial + * window, we would not send the last segment + * if we skip considering the option length here. + * Note: this may not work when tcp headers change + * very dynamically in the future. + */ + if ((((tp->t_flags & TF_SIGNATURE) ? + PADTCPOLEN(TCPOLEN_SIGNATURE) : 0) + + ((tp->t_flags & TF_RCVD_TSTMP) ? + PADTCPOLEN(TCPOLEN_TIMESTAMP) : 0) + + len) >= tp->t_maxseg) + goto send; + /* * NOTE! on localhost connections an 'ack' from the remote * end may occur synchronously with the output and cause * us to flush a buffer queued with moretocome. XXX diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index fcd8e475e066..a99898b8081e 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -3013,7 +3013,6 @@ tcp_maxseg(const struct tcpcb *tp) * but this is harmless, since result of tcp_maxseg() is used * only in cwnd and ssthresh estimations. */ -#define PAD(len) ((((len) / 4) + !!((len) % 4)) * 4) if (TCPS_HAVEESTABLISHED(tp->t_state)) { if (tp->t_flags & TF_RCVD_TSTMP) optlen = TCPOLEN_TSTAMP_APPA; @@ -3021,26 +3020,26 @@ tcp_maxseg(const struct tcpcb *tp) optlen = 0; #if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) if (tp->t_flags & TF_SIGNATURE) - optlen += PAD(TCPOLEN_SIGNATURE); + optlen += PADTCPOLEN(TCPOLEN_SIGNATURE); #endif if ((tp->t_flags & TF_SACK_PERMIT) && tp->rcv_numsacks > 0) { optlen += TCPOLEN_SACKHDR; optlen += tp->rcv_numsacks * TCPOLEN_SACK; - optlen = PAD(optlen); + optlen = PADTCPOLEN(optlen); } } else { if (tp->t_flags & TF_REQ_TSTMP) optlen = TCPOLEN_TSTAMP_APPA; else - optlen = PAD(TCPOLEN_MAXSEG); + optlen = PADTCPOLEN(TCPOLEN_MAXSEG); if (tp->t_flags & TF_REQ_SCALE) - optlen += PAD(TCPOLEN_WINDOW); + optlen += PADTCPOLEN(TCPOLEN_WINDOW); #if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) if (tp->t_flags & TF_SIGNATURE) - optlen += PAD(TCPOLEN_SIGNATURE); + optlen += PADTCPOLEN(TCPOLEN_SIGNATURE); #endif if (tp->t_flags & TF_SACK_PERMIT) - optlen += PAD(TCPOLEN_SACK_PERMITTED); + optlen += PADTCPOLEN(TCPOLEN_SACK_PERMITTED); } #undef PAD optlen = min(optlen, TCP_MAXOLEN); |