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
This commit is contained in:
parent
1567c937e2
commit
e399566123
@ -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 */
|
||||
|
@ -590,6 +590,20 @@ tcp_output(struct tcpcb *tp)
|
||||
if (len) {
|
||||
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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user