return cwnd;
 }
 
+/* With pacing at lower layers, there's often less data "in the network" than
+ * "in flight". With TSQ and departure time pacing at lower layers (e.g. fq),
+ * we often have several skbs queued in the pacing layer with a pre-scheduled
+ * earliest departure time (EDT). BBR adapts its pacing rate based on the
+ * inflight level that it estimates has already been "baked in" by previous
+ * departure time decisions. We calculate a rough estimate of the number of our
+ * packets that might be in the network at the earliest departure time for the
+ * next skb scheduled:
+ *   in_network_at_edt = inflight_at_edt - (EDT - now) * bw
+ * If we're increasing inflight, then we want to know if the transmit of the
+ * EDT skb will push inflight above the target, so inflight_at_edt includes
+ * bbr_tso_segs_goal() from the skb departing at EDT. If decreasing inflight,
+ * then estimate if inflight will sink too low just before the EDT transmit.
+ */
+static u32 bbr_packets_in_net_at_edt(struct sock *sk, u32 inflight_now)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       struct bbr *bbr = inet_csk_ca(sk);
+       u64 now_ns, edt_ns, interval_us;
+       u32 interval_delivered, inflight_at_edt;
+
+       now_ns = tp->tcp_clock_cache;
+       edt_ns = max(tp->tcp_wstamp_ns, now_ns);
+       interval_us = div_u64(edt_ns - now_ns, NSEC_PER_USEC);
+       interval_delivered = (u64)bbr_bw(sk) * interval_us >> BW_SCALE;
+       inflight_at_edt = inflight_now;
+       if (bbr->pacing_gain > BBR_UNIT)              /* increasing inflight */
+               inflight_at_edt += bbr_tso_segs_goal(sk);  /* include EDT skb */
+       if (interval_delivered >= inflight_at_edt)
+               return 0;
+       return inflight_at_edt - interval_delivered;
+}
+
 /* An optimization in BBR to reduce losses: On the first round of recovery, we
  * follow the packet conservation principle: send P packets per P packets acked.
  * After that, we slow-start and send at most 2*P packets per P packets acked.
        if (bbr->pacing_gain == BBR_UNIT)
                return is_full_length;          /* just use wall clock time */
 
-       inflight = rs->prior_in_flight;  /* what was in-flight before ACK? */
+       inflight = bbr_packets_in_net_at_edt(sk, rs->prior_in_flight);
        bw = bbr_max_bw(sk);
 
        /* A pacing_gain > 1.0 probes for bw by trying to raise inflight to at
                                bbr_target_cwnd(sk, bbr_max_bw(sk), BBR_UNIT);
        }       /* fall through to check if in-flight is already small: */
        if (bbr->mode == BBR_DRAIN &&
-           tcp_packets_in_flight(tcp_sk(sk)) <=
+           bbr_packets_in_net_at_edt(sk, tcp_packets_in_flight(tcp_sk(sk))) <=
            bbr_target_cwnd(sk, bbr_max_bw(sk), BBR_UNIT))
                bbr_reset_probe_bw_mode(sk);  /* we estimate queue is drained */
 }