- if ((tp->t_flags & TF_RXWIN0SENT) == 0 &&
- (th->th_flags & TH_PUSH) == 0 &&
- ((tp->t_unacksegs == 1) ||
- ((tp->t_flags & TF_STRETCHACK) != 0 &&
- tp->t_unacksegs < (maxseg_unacked)))) {
- return 1;
+ if (tcp_ack_strategy == TCP_ACK_STRATEGY_LEGACY) {
+ if ((tp->t_flags & TF_RXWIN0SENT) == 0 &&
+ (th->th_flags & TH_PUSH) == 0 &&
+ ((tp->t_unacksegs == 1) ||
+ ((tp->t_flags & TF_STRETCHACK) &&
+ tp->t_unacksegs < maxseg_unacked))) {
+ return 1;
+ }
+ } else {
+ uint32_t recwin;
+
+ /* Get the receive-window we would announce */
+ recwin = tcp_sbspace(tp);
+ if (recwin > (uint32_t)(TCP_MAXWIN << tp->rcv_scale)) {
+ recwin = (uint32_t)(TCP_MAXWIN << tp->rcv_scale);
+ }
+
+ /* Delay ACK, if:
+ *
+ * 1. We are not sending a zero-window
+ * 2. We are not forcing fast ACKs
+ * 3. We have more than the low-water mark in receive-buffer
+ * 4. The receive-window is not increasing
+ * 5. We have less than or equal of an MSS unacked or
+ * Window actually has been growing larger than the initial value by half of it.
+ * (this makes sure that during ramp-up we ACK every second MSS
+ * until we pass the tcp_recvspace * 1.5-threshold)
+ * 6. We haven't waited for half a BDP
+ *
+ * (a note on 6: The receive-window is
+ * roughly 2 BDP. Thus, recwin / 4 means half a BDP and
+ * thus we enforce an ACK roughly twice per RTT - even
+ * if the app does not read)
+ */
+ if ((tp->t_flags & TF_RXWIN0SENT) == 0 &&
+ tp->t_forced_acks == 0 &&
+ tp->t_inpcb->inp_socket->so_rcv.sb_cc > tp->t_inpcb->inp_socket->so_rcv.sb_lowat &&
+ recwin <= tp->t_last_recwin &&
+ (tp->rcv_nxt - tp->last_ack_sent <= tp->t_maxseg ||
+ recwin > (uint32_t)(tcp_recvspace + (tcp_recvspace >> 1))) &&
+ (tp->rcv_nxt - tp->last_ack_sent) < (recwin >> 2)) {
+ tp->t_stat.acks_delayed++;
+ return 1;
+ }