+
+static int
+tcp_recv_throttle (struct tcpcb *tp)
+{
+ uint32_t base_rtt, newsize;
+ int32_t qdelay;
+ struct sockbuf *sbrcv = &tp->t_inpcb->inp_socket->so_rcv;
+
+ if (tcp_use_rtt_recvbg == 1 &&
+ TSTMP_SUPPORTED(tp)) {
+ /*
+ * Timestamps are supported on this connection. Use
+ * RTT to look for an increase in latency.
+ */
+
+ /*
+ * If the connection is already being throttled, leave it
+ * in that state until rtt comes closer to base rtt
+ */
+ if (tp->t_flagsext & TF_RECV_THROTTLE)
+ return (1);
+
+ base_rtt = get_base_rtt(tp);
+
+ if (base_rtt != 0 && tp->t_rttcur != 0) {
+ qdelay = tp->t_rttcur - base_rtt;
+ /*
+ * if latency increased on a background flow,
+ * return 1 to start throttling.
+ */
+ if (qdelay > target_qdelay) {
+ tp->t_flagsext |= TF_RECV_THROTTLE;
+
+ /*
+ * Reduce the recv socket buffer size to
+ * minimize latecy.
+ */
+ if (sbrcv->sb_idealsize >
+ tcp_recv_throttle_minwin) {
+ newsize = sbrcv->sb_idealsize >> 1;
+ /* Set a minimum of 16 K */
+ newsize =
+ max(newsize,
+ tcp_recv_throttle_minwin);
+ sbrcv->sb_idealsize = newsize;
+ }
+ return (1);
+ } else {
+ return (0);
+ }
+ }
+ }
+
+ /*
+ * Timestamps are not supported or there is no good RTT
+ * measurement. Use IPDV in this case.
+ */
+ if (tp->acc_iaj > tcp_acc_iaj_react_limit)
+ return (1);
+
+ return (0);
+}