u8 reord;    /* reordering detected */
        } rack;
        u16     advmss;         /* Advertised MSS                       */
-       u8      unused;
+       u8      rate_app_limited:1,  /* rate_{delivered,interval_us} limited? */
+               unused:7;
        u8      nonagle     : 4,/* Disable Nagle algorithm?             */
                thin_lto    : 1,/* Use linear timeouts for thin streams */
                thin_dupack : 1,/* Fast retransmit on first dupack      */
        u32     app_limited;    /* limited until "delivered" reaches this val */
        struct skb_mstamp first_tx_mstamp;  /* start of window send phase */
        struct skb_mstamp delivered_mstamp; /* time we reached "delivered" */
+       u32     rate_delivered;    /* saved rate sample: packets delivered */
+       u32     rate_interval_us;  /* saved rate sample: time elapsed */
 
        u32     rcv_wnd;        /* Current receiver window              */
        u32     write_seq;      /* Tail(+1) of data held in tcp send buffer */
 
        __u8    tcpi_backoff;
        __u8    tcpi_options;
        __u8    tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
+       __u8    tcpi_delivery_rate_app_limited:1;
 
        __u32   tcpi_rto;
        __u32   tcpi_ato;
        __u32   tcpi_min_rtt;
        __u32   tcpi_data_segs_in;      /* RFC4898 tcpEStatsDataSegsIn */
        __u32   tcpi_data_segs_out;     /* RFC4898 tcpEStatsDataSegsOut */
+
+       __u64   tcpi_delivery_rate;
 };
 
 /* for TCP_MD5SIG socket option */
 
 {
        const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */
        const struct inet_connection_sock *icsk = inet_csk(sk);
-       u32 now = tcp_time_stamp;
+       u32 now = tcp_time_stamp, intv;
        unsigned int start;
        int notsent_bytes;
        u64 rate64;
        info->tcpi_min_rtt = tcp_min_rtt(tp);
        info->tcpi_data_segs_in = tp->data_segs_in;
        info->tcpi_data_segs_out = tp->data_segs_out;
+
+       info->tcpi_delivery_rate_app_limited = tp->rate_app_limited ? 1 : 0;
+       rate = READ_ONCE(tp->rate_delivered);
+       intv = READ_ONCE(tp->rate_interval_us);
+       if (rate && intv) {
+               rate64 = (u64)rate * tp->mss_cache * USEC_PER_SEC;
+               do_div(rate64, intv);
+               put_unaligned(rate64, &info->tcpi_delivery_rate);
+       }
 }
 EXPORT_SYMBOL_GPL(tcp_get_info);
 
 
         * for connections suffer heavy or prolonged losses.
         */
        if (unlikely(rs->interval_us < tcp_min_rtt(tp))) {
-               rs->interval_us = -1;
                if (!rs->is_retrans)
                        pr_debug("tcp rate: %ld %d %u %u %u\n",
                                 rs->interval_us, rs->delivered,
                                 inet_csk(sk)->icsk_ca_state,
                                 tp->rx_opt.sack_ok, tcp_min_rtt(tp));
+               rs->interval_us = -1;
+               return;
+       }
+
+       /* Record the last non-app-limited or the highest app-limited bw */
+       if (!rs->is_app_limited ||
+           ((u64)rs->delivered * tp->rate_interval_us >=
+            (u64)tp->rate_delivered * rs->interval_us)) {
+               tp->rate_delivered = rs->delivered;
+               tp->rate_interval_us = rs->interval_us;
+               tp->rate_app_limited = rs->is_app_limited;
        }
 }