mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 20:54:10 +08:00
tcp: switch rtt estimations to usec resolution
Upcoming congestion controls for TCP require usec resolution for RTT estimations. Millisecond resolution is simply not enough these days. FQ/pacing in DC environments also require this change for finer control and removal of bimodal behavior due to the current hack in tcp_update_pacing_rate() for 'small rtt' TCP_CONG_RTT_STAMP is no longer needed. As Julian Anastasov pointed out, we need to keep user compatibility : tcp_metrics used to export RTT and RTTVAR in msec resolution, so we added RTT_US and RTTVAR_US. An iproute2 patch is needed to use the new attributes if provided by the kernel. In this example ss command displays a srtt of 32 usecs (10Gbit link) lpk51:~# ./ss -i dst lpk52 Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port tcp ESTAB 0 1 10.246.11.51:42959 10.246.11.52:64614 cubic wscale:6,6 rto:201 rtt:0.032/0.001 ato:40 mss:1448 cwnd:10 send 3620.0Mbps pacing_rate 7240.0Mbps unacked:1 rcv_rtt:993 rcv_space:29559 Updated iproute2 ip command displays : lpk51:~# ./ip tcp_metrics | grep 10.246.11.52 10.246.11.52 age 561.914sec cwnd 10 rtt 274us rttvar 213us source 10.246.11.51 Old binary displays : lpk51:~# ip tcp_metrics | grep 10.246.11.52 10.246.11.52 age 561.914sec cwnd 10 rtt 250us rttvar 125us source 10.246.11.51 With help from Julian Anastasov, Stephen Hemminger and Yuchung Cheng Signed-off-by: Eric Dumazet <edumazet@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Cc: Stephen Hemminger <stephen@networkplumber.org> Cc: Yuchung Cheng <ycheng@google.com> Cc: Larry Brakmo <brakmo@google.com> Cc: Julian Anastasov <ja@ssi.bg> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
363ec39235
commit
740b0f1841
@ -201,10 +201,10 @@ struct tcp_sock {
|
||||
u32 tlp_high_seq; /* snd_nxt at the time of TLP retransmit. */
|
||||
|
||||
/* RTT measurement */
|
||||
u32 srtt; /* smoothed round trip time << 3 */
|
||||
u32 mdev; /* medium deviation */
|
||||
u32 mdev_max; /* maximal mdev for the last rtt period */
|
||||
u32 rttvar; /* smoothed mdev_max */
|
||||
u32 srtt_us; /* smoothed round trip time << 3 in usecs */
|
||||
u32 mdev_us; /* medium deviation */
|
||||
u32 mdev_max_us; /* maximal mdev for the last rtt period */
|
||||
u32 rttvar_us; /* smoothed mdev_max */
|
||||
u32 rtt_seq; /* sequence number to update rttvar */
|
||||
|
||||
u32 packets_out; /* Packets which are "in flight" */
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/cryptohash.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/ktime.h>
|
||||
|
||||
#include <net/inet_connection_sock.h>
|
||||
#include <net/inet_timewait_sock.h>
|
||||
@ -478,7 +479,6 @@ int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
|
||||
struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
|
||||
struct ip_options *opt);
|
||||
#ifdef CONFIG_SYN_COOKIES
|
||||
#include <linux/ktime.h>
|
||||
|
||||
/* Syncookies use a monotonic timer which increments every 64 seconds.
|
||||
* This counter is used both as a hash input and partially encoded into
|
||||
@ -619,7 +619,7 @@ static inline void tcp_bound_rto(const struct sock *sk)
|
||||
|
||||
static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
|
||||
{
|
||||
return (tp->srtt >> 3) + tp->rttvar;
|
||||
return usecs_to_jiffies((tp->srtt_us >> 3) + tp->rttvar_us);
|
||||
}
|
||||
|
||||
static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
|
||||
@ -656,6 +656,11 @@ static inline u32 tcp_rto_min(struct sock *sk)
|
||||
return rto_min;
|
||||
}
|
||||
|
||||
static inline u32 tcp_rto_min_us(struct sock *sk)
|
||||
{
|
||||
return jiffies_to_usecs(tcp_rto_min(sk));
|
||||
}
|
||||
|
||||
/* Compute the actual receive window we are currently advertising.
|
||||
* Rcv_nxt can be after the window if our peer push more data
|
||||
* than the offered window.
|
||||
@ -778,7 +783,6 @@ enum tcp_ca_event {
|
||||
#define TCP_CA_BUF_MAX (TCP_CA_NAME_MAX*TCP_CA_MAX)
|
||||
|
||||
#define TCP_CONG_NON_RESTRICTED 0x1
|
||||
#define TCP_CONG_RTT_STAMP 0x2
|
||||
|
||||
struct tcp_congestion_ops {
|
||||
struct list_head list;
|
||||
|
@ -11,12 +11,15 @@
|
||||
#define TCP_METRICS_GENL_VERSION 0x1
|
||||
|
||||
enum tcp_metric_index {
|
||||
TCP_METRIC_RTT,
|
||||
TCP_METRIC_RTTVAR,
|
||||
TCP_METRIC_RTT, /* in ms units */
|
||||
TCP_METRIC_RTTVAR, /* in ms units */
|
||||
TCP_METRIC_SSTHRESH,
|
||||
TCP_METRIC_CWND,
|
||||
TCP_METRIC_REORDERING,
|
||||
|
||||
TCP_METRIC_RTT_US, /* in usec units */
|
||||
TCP_METRIC_RTTVAR_US, /* in usec units */
|
||||
|
||||
/* Always last. */
|
||||
__TCP_METRIC_MAX,
|
||||
};
|
||||
|
@ -387,7 +387,7 @@ void tcp_init_sock(struct sock *sk)
|
||||
INIT_LIST_HEAD(&tp->tsq_node);
|
||||
|
||||
icsk->icsk_rto = TCP_TIMEOUT_INIT;
|
||||
tp->mdev = TCP_TIMEOUT_INIT;
|
||||
tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT);
|
||||
|
||||
/* So many TCP implementations out there (incorrectly) count the
|
||||
* initial SYN frame in their delayed-ACK and congestion control
|
||||
@ -2339,7 +2339,7 @@ int tcp_disconnect(struct sock *sk, int flags)
|
||||
|
||||
sk->sk_shutdown = 0;
|
||||
sock_reset_flag(sk, SOCK_DONE);
|
||||
tp->srtt = 0;
|
||||
tp->srtt_us = 0;
|
||||
if ((tp->write_seq += tp->max_window + 2) == 0)
|
||||
tp->write_seq = 1;
|
||||
icsk->icsk_backoff = 0;
|
||||
@ -2783,8 +2783,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
|
||||
|
||||
info->tcpi_pmtu = icsk->icsk_pmtu_cookie;
|
||||
info->tcpi_rcv_ssthresh = tp->rcv_ssthresh;
|
||||
info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3;
|
||||
info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2;
|
||||
info->tcpi_rtt = tp->srtt_us >> 3;
|
||||
info->tcpi_rttvar = tp->mdev_us >> 2;
|
||||
info->tcpi_snd_ssthresh = tp->snd_ssthresh;
|
||||
info->tcpi_snd_cwnd = tp->snd_cwnd;
|
||||
info->tcpi_advmss = tp->advmss;
|
||||
|
@ -476,10 +476,6 @@ static int __init cubictcp_register(void)
|
||||
/* divide by bic_scale and by constant Srtt (100ms) */
|
||||
do_div(cube_factor, bic_scale * 10);
|
||||
|
||||
/* hystart needs ms clock resolution */
|
||||
if (hystart && HZ < 1000)
|
||||
cubictcp.flags |= TCP_CONG_RTT_STAMP;
|
||||
|
||||
return tcp_register_congestion_control(&cubictcp);
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ struct hybla {
|
||||
u32 rho2; /* Rho * Rho, integer part */
|
||||
u32 rho_3ls; /* Rho parameter, <<3 */
|
||||
u32 rho2_7ls; /* Rho^2, <<7 */
|
||||
u32 minrtt; /* Minimum smoothed round trip time value seen */
|
||||
u32 minrtt_us; /* Minimum smoothed round trip time value seen */
|
||||
};
|
||||
|
||||
/* Hybla reference round trip time (default= 1/40 sec = 25 ms), in ms */
|
||||
@ -35,7 +35,9 @@ static inline void hybla_recalc_param (struct sock *sk)
|
||||
{
|
||||
struct hybla *ca = inet_csk_ca(sk);
|
||||
|
||||
ca->rho_3ls = max_t(u32, tcp_sk(sk)->srtt / msecs_to_jiffies(rtt0), 8);
|
||||
ca->rho_3ls = max_t(u32,
|
||||
tcp_sk(sk)->srtt_us / (rtt0 * USEC_PER_MSEC),
|
||||
8U);
|
||||
ca->rho = ca->rho_3ls >> 3;
|
||||
ca->rho2_7ls = (ca->rho_3ls * ca->rho_3ls) << 1;
|
||||
ca->rho2 = ca->rho2_7ls >> 7;
|
||||
@ -59,7 +61,7 @@ static void hybla_init(struct sock *sk)
|
||||
hybla_recalc_param(sk);
|
||||
|
||||
/* set minimum rtt as this is the 1st ever seen */
|
||||
ca->minrtt = tp->srtt;
|
||||
ca->minrtt_us = tp->srtt_us;
|
||||
tp->snd_cwnd = ca->rho;
|
||||
}
|
||||
|
||||
@ -94,9 +96,9 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 acked,
|
||||
int is_slowstart = 0;
|
||||
|
||||
/* Recalculate rho only if this srtt is the lowest */
|
||||
if (tp->srtt < ca->minrtt){
|
||||
if (tp->srtt_us < ca->minrtt_us) {
|
||||
hybla_recalc_param(sk);
|
||||
ca->minrtt = tp->srtt;
|
||||
ca->minrtt_us = tp->srtt_us;
|
||||
}
|
||||
|
||||
if (!tcp_is_cwnd_limited(sk, in_flight))
|
||||
|
@ -325,7 +325,6 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,
|
||||
}
|
||||
|
||||
static struct tcp_congestion_ops tcp_illinois __read_mostly = {
|
||||
.flags = TCP_CONG_RTT_STAMP,
|
||||
.init = tcp_illinois_init,
|
||||
.ssthresh = tcp_illinois_ssthresh,
|
||||
.cong_avoid = tcp_illinois_cong_avoid,
|
||||
|
@ -667,11 +667,11 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb)
|
||||
* To save cycles in the RFC 1323 implementation it was better to break
|
||||
* it up into three procedures. -- erics
|
||||
*/
|
||||
static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)
|
||||
static void tcp_rtt_estimator(struct sock *sk, long mrtt_us)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
long m = mrtt; /* RTT */
|
||||
u32 srtt = tp->srtt;
|
||||
long m = mrtt_us; /* RTT */
|
||||
u32 srtt = tp->srtt_us;
|
||||
|
||||
/* The following amusing code comes from Jacobson's
|
||||
* article in SIGCOMM '88. Note that rtt and mdev
|
||||
@ -694,7 +694,7 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)
|
||||
srtt += m; /* rtt = 7/8 rtt + 1/8 new */
|
||||
if (m < 0) {
|
||||
m = -m; /* m is now abs(error) */
|
||||
m -= (tp->mdev >> 2); /* similar update on mdev */
|
||||
m -= (tp->mdev_us >> 2); /* similar update on mdev */
|
||||
/* This is similar to one of Eifel findings.
|
||||
* Eifel blocks mdev updates when rtt decreases.
|
||||
* This solution is a bit different: we use finer gain
|
||||
@ -706,28 +706,29 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt)
|
||||
if (m > 0)
|
||||
m >>= 3;
|
||||
} else {
|
||||
m -= (tp->mdev >> 2); /* similar update on mdev */
|
||||
m -= (tp->mdev_us >> 2); /* similar update on mdev */
|
||||
}
|
||||
tp->mdev += m; /* mdev = 3/4 mdev + 1/4 new */
|
||||
if (tp->mdev > tp->mdev_max) {
|
||||
tp->mdev_max = tp->mdev;
|
||||
if (tp->mdev_max > tp->rttvar)
|
||||
tp->rttvar = tp->mdev_max;
|
||||
tp->mdev_us += m; /* mdev = 3/4 mdev + 1/4 new */
|
||||
if (tp->mdev_us > tp->mdev_max_us) {
|
||||
tp->mdev_max_us = tp->mdev_us;
|
||||
if (tp->mdev_max_us > tp->rttvar_us)
|
||||
tp->rttvar_us = tp->mdev_max_us;
|
||||
}
|
||||
if (after(tp->snd_una, tp->rtt_seq)) {
|
||||
if (tp->mdev_max < tp->rttvar)
|
||||
tp->rttvar -= (tp->rttvar - tp->mdev_max) >> 2;
|
||||
if (tp->mdev_max_us < tp->rttvar_us)
|
||||
tp->rttvar_us -= (tp->rttvar_us - tp->mdev_max_us) >> 2;
|
||||
tp->rtt_seq = tp->snd_nxt;
|
||||
tp->mdev_max = tcp_rto_min(sk);
|
||||
tp->mdev_max_us = tcp_rto_min_us(sk);
|
||||
}
|
||||
} else {
|
||||
/* no previous measure. */
|
||||
srtt = m << 3; /* take the measured time to be rtt */
|
||||
tp->mdev = m << 1; /* make sure rto = 3*rtt */
|
||||
tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));
|
||||
tp->mdev_us = m << 1; /* make sure rto = 3*rtt */
|
||||
tp->rttvar_us = max(tp->mdev_us, tcp_rto_min_us(sk));
|
||||
tp->mdev_max_us = tp->rttvar_us;
|
||||
tp->rtt_seq = tp->snd_nxt;
|
||||
}
|
||||
tp->srtt = max(1U, srtt);
|
||||
tp->srtt_us = max(1U, srtt);
|
||||
}
|
||||
|
||||
/* Set the sk_pacing_rate to allow proper sizing of TSO packets.
|
||||
@ -742,20 +743,12 @@ static void tcp_update_pacing_rate(struct sock *sk)
|
||||
u64 rate;
|
||||
|
||||
/* set sk_pacing_rate to 200 % of current rate (mss * cwnd / srtt) */
|
||||
rate = (u64)tp->mss_cache * 2 * (HZ << 3);
|
||||
rate = (u64)tp->mss_cache * 2 * (USEC_PER_SEC << 3);
|
||||
|
||||
rate *= max(tp->snd_cwnd, tp->packets_out);
|
||||
|
||||
/* Correction for small srtt and scheduling constraints.
|
||||
* For small rtt, consider noise is too high, and use
|
||||
* the minimal value (srtt = 1 -> 125 us for HZ=1000)
|
||||
*
|
||||
* We probably need usec resolution in the future.
|
||||
* Note: This also takes care of possible srtt=0 case,
|
||||
* when tcp_rtt_estimator() was not yet called.
|
||||
*/
|
||||
if (tp->srtt > 8 + 2)
|
||||
do_div(rate, tp->srtt);
|
||||
if (likely(tp->srtt_us))
|
||||
do_div(rate, tp->srtt_us);
|
||||
|
||||
/* ACCESS_ONCE() is needed because sch_fq fetches sk_pacing_rate
|
||||
* without any lock. We want to make sure compiler wont store
|
||||
@ -1122,10 +1115,10 @@ static bool tcp_check_dsack(struct sock *sk, const struct sk_buff *ack_skb,
|
||||
}
|
||||
|
||||
struct tcp_sacktag_state {
|
||||
int reord;
|
||||
int fack_count;
|
||||
int flag;
|
||||
s32 rtt; /* RTT measured by SACKing never-retransmitted data */
|
||||
int reord;
|
||||
int fack_count;
|
||||
long rtt_us; /* RTT measured by SACKing never-retransmitted data */
|
||||
int flag;
|
||||
};
|
||||
|
||||
/* Check if skb is fully within the SACK block. In presence of GSO skbs,
|
||||
@ -1186,7 +1179,8 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
|
||||
static u8 tcp_sacktag_one(struct sock *sk,
|
||||
struct tcp_sacktag_state *state, u8 sacked,
|
||||
u32 start_seq, u32 end_seq,
|
||||
int dup_sack, int pcount, u32 xmit_time)
|
||||
int dup_sack, int pcount,
|
||||
const struct skb_mstamp *xmit_time)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
int fack_count = state->fack_count;
|
||||
@ -1227,8 +1221,13 @@ static u8 tcp_sacktag_one(struct sock *sk,
|
||||
if (!after(end_seq, tp->high_seq))
|
||||
state->flag |= FLAG_ORIG_SACK_ACKED;
|
||||
/* Pick the earliest sequence sacked for RTT */
|
||||
if (state->rtt < 0)
|
||||
state->rtt = tcp_time_stamp - xmit_time;
|
||||
if (state->rtt_us < 0) {
|
||||
struct skb_mstamp now;
|
||||
|
||||
skb_mstamp_get(&now);
|
||||
state->rtt_us = skb_mstamp_us_delta(&now,
|
||||
xmit_time);
|
||||
}
|
||||
}
|
||||
|
||||
if (sacked & TCPCB_LOST) {
|
||||
@ -1287,7 +1286,7 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
|
||||
*/
|
||||
tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked,
|
||||
start_seq, end_seq, dup_sack, pcount,
|
||||
TCP_SKB_CB(skb)->when);
|
||||
&skb->skb_mstamp);
|
||||
|
||||
if (skb == tp->lost_skb_hint)
|
||||
tp->lost_cnt_hint += pcount;
|
||||
@ -1565,7 +1564,7 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk,
|
||||
TCP_SKB_CB(skb)->end_seq,
|
||||
dup_sack,
|
||||
tcp_skb_pcount(skb),
|
||||
TCP_SKB_CB(skb)->when);
|
||||
&skb->skb_mstamp);
|
||||
|
||||
if (!before(TCP_SKB_CB(skb)->seq,
|
||||
tcp_highest_sack_seq(tp)))
|
||||
@ -1622,7 +1621,7 @@ static int tcp_sack_cache_ok(const struct tcp_sock *tp, const struct tcp_sack_bl
|
||||
|
||||
static int
|
||||
tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
|
||||
u32 prior_snd_una, s32 *sack_rtt)
|
||||
u32 prior_snd_una, long *sack_rtt_us)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
const unsigned char *ptr = (skb_transport_header(ack_skb) +
|
||||
@ -1640,7 +1639,7 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
|
||||
|
||||
state.flag = 0;
|
||||
state.reord = tp->packets_out;
|
||||
state.rtt = -1;
|
||||
state.rtt_us = -1L;
|
||||
|
||||
if (!tp->sacked_out) {
|
||||
if (WARN_ON(tp->fackets_out))
|
||||
@ -1824,7 +1823,7 @@ out:
|
||||
WARN_ON((int)tp->retrans_out < 0);
|
||||
WARN_ON((int)tcp_packets_in_flight(tp) < 0);
|
||||
#endif
|
||||
*sack_rtt = state.rtt;
|
||||
*sack_rtt_us = state.rtt_us;
|
||||
return state.flag;
|
||||
}
|
||||
|
||||
@ -2034,10 +2033,12 @@ static bool tcp_pause_early_retransmit(struct sock *sk, int flag)
|
||||
* available, or RTO is scheduled to fire first.
|
||||
*/
|
||||
if (sysctl_tcp_early_retrans < 2 || sysctl_tcp_early_retrans > 3 ||
|
||||
(flag & FLAG_ECE) || !tp->srtt)
|
||||
(flag & FLAG_ECE) || !tp->srtt_us)
|
||||
return false;
|
||||
|
||||
delay = max_t(unsigned long, (tp->srtt >> 5), msecs_to_jiffies(2));
|
||||
delay = max(usecs_to_jiffies(tp->srtt_us >> 5),
|
||||
msecs_to_jiffies(2));
|
||||
|
||||
if (!time_after(inet_csk(sk)->icsk_timeout, (jiffies + delay)))
|
||||
return false;
|
||||
|
||||
@ -2884,7 +2885,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked,
|
||||
}
|
||||
|
||||
static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
|
||||
s32 seq_rtt, s32 sack_rtt)
|
||||
long seq_rtt_us, long sack_rtt_us)
|
||||
{
|
||||
const struct tcp_sock *tp = tcp_sk(sk);
|
||||
|
||||
@ -2894,10 +2895,10 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
|
||||
* is acked (RFC6298).
|
||||
*/
|
||||
if (flag & FLAG_RETRANS_DATA_ACKED)
|
||||
seq_rtt = -1;
|
||||
seq_rtt_us = -1L;
|
||||
|
||||
if (seq_rtt < 0)
|
||||
seq_rtt = sack_rtt;
|
||||
if (seq_rtt_us < 0)
|
||||
seq_rtt_us = sack_rtt_us;
|
||||
|
||||
/* RTTM Rule: A TSecr value received in a segment is used to
|
||||
* update the averaged RTT measurement only if the segment
|
||||
@ -2905,14 +2906,14 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
|
||||
* left edge of the send window.
|
||||
* See draft-ietf-tcplw-high-performance-00, section 3.3.
|
||||
*/
|
||||
if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
|
||||
if (seq_rtt_us < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
|
||||
flag & FLAG_ACKED)
|
||||
seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
|
||||
seq_rtt_us = jiffies_to_usecs(tcp_time_stamp - tp->rx_opt.rcv_tsecr);
|
||||
|
||||
if (seq_rtt < 0)
|
||||
if (seq_rtt_us < 0)
|
||||
return false;
|
||||
|
||||
tcp_rtt_estimator(sk, seq_rtt);
|
||||
tcp_rtt_estimator(sk, seq_rtt_us);
|
||||
tcp_set_rto(sk);
|
||||
|
||||
/* RFC6298: only reset backoff on valid RTT measurement. */
|
||||
@ -2924,16 +2925,16 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
|
||||
static void tcp_synack_rtt_meas(struct sock *sk, const u32 synack_stamp)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
s32 seq_rtt = -1;
|
||||
long seq_rtt_us = -1L;
|
||||
|
||||
if (synack_stamp && !tp->total_retrans)
|
||||
seq_rtt = tcp_time_stamp - synack_stamp;
|
||||
seq_rtt_us = jiffies_to_usecs(tcp_time_stamp - synack_stamp);
|
||||
|
||||
/* If the ACK acks both the SYNACK and the (Fast Open'd) data packets
|
||||
* sent in SYN_RECV, SYNACK RTT is the smooth RTT computed in tcp_ack()
|
||||
*/
|
||||
if (!tp->srtt)
|
||||
tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1);
|
||||
if (!tp->srtt_us)
|
||||
tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt_us, -1L);
|
||||
}
|
||||
|
||||
static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 acked, u32 in_flight)
|
||||
@ -3022,26 +3023,27 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb)
|
||||
* arrived at the other end.
|
||||
*/
|
||||
static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
|
||||
u32 prior_snd_una, s32 sack_rtt)
|
||||
u32 prior_snd_una, long sack_rtt_us)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
const struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
struct sk_buff *skb;
|
||||
u32 now = tcp_time_stamp;
|
||||
bool fully_acked = true;
|
||||
int flag = 0;
|
||||
u32 pkts_acked = 0;
|
||||
u32 reord = tp->packets_out;
|
||||
struct skb_mstamp first_ackt, last_ackt, now;
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
u32 prior_sacked = tp->sacked_out;
|
||||
s32 seq_rtt = -1;
|
||||
s32 ca_seq_rtt = -1;
|
||||
ktime_t last_ackt = net_invalid_timestamp();
|
||||
u32 reord = tp->packets_out;
|
||||
bool fully_acked = true;
|
||||
long ca_seq_rtt_us = -1L;
|
||||
long seq_rtt_us = -1L;
|
||||
struct sk_buff *skb;
|
||||
u32 pkts_acked = 0;
|
||||
bool rtt_update;
|
||||
int flag = 0;
|
||||
|
||||
first_ackt.v64 = 0;
|
||||
|
||||
while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) {
|
||||
struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
|
||||
u32 acked_pcount;
|
||||
u8 sacked = scb->sacked;
|
||||
u32 acked_pcount;
|
||||
|
||||
/* Determine how many packets and what bytes were acked, tso and else */
|
||||
if (after(scb->end_seq, tp->snd_una)) {
|
||||
@ -3063,11 +3065,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
|
||||
tp->retrans_out -= acked_pcount;
|
||||
flag |= FLAG_RETRANS_DATA_ACKED;
|
||||
} else {
|
||||
ca_seq_rtt = now - scb->when;
|
||||
last_ackt = skb->tstamp;
|
||||
if (seq_rtt < 0) {
|
||||
seq_rtt = ca_seq_rtt;
|
||||
}
|
||||
last_ackt = skb->skb_mstamp;
|
||||
if (!first_ackt.v64)
|
||||
first_ackt = last_ackt;
|
||||
|
||||
if (!(sacked & TCPCB_SACKED_ACKED))
|
||||
reord = min(pkts_acked, reord);
|
||||
if (!after(scb->end_seq, tp->high_seq))
|
||||
@ -3113,7 +3114,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
|
||||
if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
|
||||
flag |= FLAG_SACK_RENEGING;
|
||||
|
||||
rtt_update = tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt);
|
||||
skb_mstamp_get(&now);
|
||||
if (first_ackt.v64) {
|
||||
seq_rtt_us = skb_mstamp_us_delta(&now, &first_ackt);
|
||||
ca_seq_rtt_us = skb_mstamp_us_delta(&now, &last_ackt);
|
||||
}
|
||||
|
||||
rtt_update = tcp_ack_update_rtt(sk, flag, seq_rtt_us, sack_rtt_us);
|
||||
|
||||
if (flag & FLAG_ACKED) {
|
||||
const struct tcp_congestion_ops *ca_ops
|
||||
@ -3141,25 +3148,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
|
||||
|
||||
tp->fackets_out -= min(pkts_acked, tp->fackets_out);
|
||||
|
||||
if (ca_ops->pkts_acked) {
|
||||
s32 rtt_us = -1;
|
||||
if (ca_ops->pkts_acked)
|
||||
ca_ops->pkts_acked(sk, pkts_acked, ca_seq_rtt_us);
|
||||
|
||||
/* Is the ACK triggering packet unambiguous? */
|
||||
if (!(flag & FLAG_RETRANS_DATA_ACKED)) {
|
||||
/* High resolution needed and available? */
|
||||
if (ca_ops->flags & TCP_CONG_RTT_STAMP &&
|
||||
!ktime_equal(last_ackt,
|
||||
net_invalid_timestamp()))
|
||||
rtt_us = ktime_us_delta(ktime_get_real(),
|
||||
last_ackt);
|
||||
else if (ca_seq_rtt >= 0)
|
||||
rtt_us = jiffies_to_usecs(ca_seq_rtt);
|
||||
}
|
||||
|
||||
ca_ops->pkts_acked(sk, pkts_acked, rtt_us);
|
||||
}
|
||||
} else if (skb && rtt_update && sack_rtt >= 0 &&
|
||||
sack_rtt > (s32)(now - TCP_SKB_CB(skb)->when)) {
|
||||
} else if (skb && rtt_update && sack_rtt_us >= 0 &&
|
||||
sack_rtt_us > skb_mstamp_us_delta(&now, &skb->skb_mstamp)) {
|
||||
/* Do not re-arm RTO if the sack RTT is measured from data sent
|
||||
* after when the head was last (re)transmitted. Otherwise the
|
||||
* timeout may continue to extend in loss recovery.
|
||||
@ -3369,12 +3362,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
|
||||
u32 ack_seq = TCP_SKB_CB(skb)->seq;
|
||||
u32 ack = TCP_SKB_CB(skb)->ack_seq;
|
||||
bool is_dupack = false;
|
||||
u32 prior_in_flight, prior_cwnd = tp->snd_cwnd, prior_rtt = tp->srtt;
|
||||
u32 prior_in_flight;
|
||||
u32 prior_fackets;
|
||||
int prior_packets = tp->packets_out;
|
||||
const int prior_unsacked = tp->packets_out - tp->sacked_out;
|
||||
int acked = 0; /* Number of packets newly acked */
|
||||
s32 sack_rtt = -1;
|
||||
long sack_rtt_us = -1L;
|
||||
|
||||
/* If the ack is older than previous acks
|
||||
* then we can probably ignore it.
|
||||
@ -3432,7 +3425,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
|
||||
|
||||
if (TCP_SKB_CB(skb)->sacked)
|
||||
flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
|
||||
&sack_rtt);
|
||||
&sack_rtt_us);
|
||||
|
||||
if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb)))
|
||||
flag |= FLAG_ECE;
|
||||
@ -3451,7 +3444,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
|
||||
|
||||
/* See if we can take anything off of the retransmit queue. */
|
||||
acked = tp->packets_out;
|
||||
flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, sack_rtt);
|
||||
flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una,
|
||||
sack_rtt_us);
|
||||
acked -= tp->packets_out;
|
||||
|
||||
/* Advance cwnd if state allows */
|
||||
@ -3474,8 +3468,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
|
||||
|
||||
if (icsk->icsk_pending == ICSK_TIME_RETRANS)
|
||||
tcp_schedule_loss_probe(sk);
|
||||
if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd)
|
||||
tcp_update_pacing_rate(sk);
|
||||
tcp_update_pacing_rate(sk);
|
||||
return 1;
|
||||
|
||||
no_queue:
|
||||
@ -3504,7 +3497,7 @@ old_ack:
|
||||
*/
|
||||
if (TCP_SKB_CB(skb)->sacked) {
|
||||
flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
|
||||
&sack_rtt);
|
||||
&sack_rtt_us);
|
||||
tcp_fastretrans_alert(sk, acked, prior_unsacked,
|
||||
is_dupack, flag);
|
||||
}
|
||||
|
@ -435,7 +435,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
|
||||
break;
|
||||
|
||||
icsk->icsk_backoff--;
|
||||
inet_csk(sk)->icsk_rto = (tp->srtt ? __tcp_set_rto(tp) :
|
||||
inet_csk(sk)->icsk_rto = (tp->srtt_us ? __tcp_set_rto(tp) :
|
||||
TCP_TIMEOUT_INIT) << icsk->icsk_backoff;
|
||||
tcp_bound_rto(sk);
|
||||
|
||||
|
@ -315,7 +315,6 @@ static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, s32 rtt_us)
|
||||
}
|
||||
|
||||
static struct tcp_congestion_ops tcp_lp __read_mostly = {
|
||||
.flags = TCP_CONG_RTT_STAMP,
|
||||
.init = tcp_lp_init,
|
||||
.ssthresh = tcp_reno_ssthresh,
|
||||
.cong_avoid = tcp_lp_cong_avoid,
|
||||
|
@ -33,6 +33,11 @@ struct tcp_fastopen_metrics {
|
||||
struct tcp_fastopen_cookie cookie;
|
||||
};
|
||||
|
||||
/* TCP_METRIC_MAX includes 2 extra fields for userspace compatibility
|
||||
* Kernel only stores RTT and RTTVAR in usec resolution
|
||||
*/
|
||||
#define TCP_METRIC_MAX_KERNEL (TCP_METRIC_MAX - 2)
|
||||
|
||||
struct tcp_metrics_block {
|
||||
struct tcp_metrics_block __rcu *tcpm_next;
|
||||
struct inetpeer_addr tcpm_saddr;
|
||||
@ -41,7 +46,7 @@ struct tcp_metrics_block {
|
||||
u32 tcpm_ts;
|
||||
u32 tcpm_ts_stamp;
|
||||
u32 tcpm_lock;
|
||||
u32 tcpm_vals[TCP_METRIC_MAX + 1];
|
||||
u32 tcpm_vals[TCP_METRIC_MAX_KERNEL + 1];
|
||||
struct tcp_fastopen_metrics tcpm_fastopen;
|
||||
|
||||
struct rcu_head rcu_head;
|
||||
@ -59,12 +64,6 @@ static u32 tcp_metric_get(struct tcp_metrics_block *tm,
|
||||
return tm->tcpm_vals[idx];
|
||||
}
|
||||
|
||||
static u32 tcp_metric_get_jiffies(struct tcp_metrics_block *tm,
|
||||
enum tcp_metric_index idx)
|
||||
{
|
||||
return msecs_to_jiffies(tm->tcpm_vals[idx]);
|
||||
}
|
||||
|
||||
static void tcp_metric_set(struct tcp_metrics_block *tm,
|
||||
enum tcp_metric_index idx,
|
||||
u32 val)
|
||||
@ -72,13 +71,6 @@ static void tcp_metric_set(struct tcp_metrics_block *tm,
|
||||
tm->tcpm_vals[idx] = val;
|
||||
}
|
||||
|
||||
static void tcp_metric_set_msecs(struct tcp_metrics_block *tm,
|
||||
enum tcp_metric_index idx,
|
||||
u32 val)
|
||||
{
|
||||
tm->tcpm_vals[idx] = jiffies_to_msecs(val);
|
||||
}
|
||||
|
||||
static bool addr_same(const struct inetpeer_addr *a,
|
||||
const struct inetpeer_addr *b)
|
||||
{
|
||||
@ -101,9 +93,11 @@ struct tcpm_hash_bucket {
|
||||
|
||||
static DEFINE_SPINLOCK(tcp_metrics_lock);
|
||||
|
||||
static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst,
|
||||
static void tcpm_suck_dst(struct tcp_metrics_block *tm,
|
||||
const struct dst_entry *dst,
|
||||
bool fastopen_clear)
|
||||
{
|
||||
u32 msval;
|
||||
u32 val;
|
||||
|
||||
tm->tcpm_stamp = jiffies;
|
||||
@ -121,8 +115,11 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst,
|
||||
val |= 1 << TCP_METRIC_REORDERING;
|
||||
tm->tcpm_lock = val;
|
||||
|
||||
tm->tcpm_vals[TCP_METRIC_RTT] = dst_metric_raw(dst, RTAX_RTT);
|
||||
tm->tcpm_vals[TCP_METRIC_RTTVAR] = dst_metric_raw(dst, RTAX_RTTVAR);
|
||||
msval = dst_metric_raw(dst, RTAX_RTT);
|
||||
tm->tcpm_vals[TCP_METRIC_RTT] = msval * USEC_PER_MSEC;
|
||||
|
||||
msval = dst_metric_raw(dst, RTAX_RTTVAR);
|
||||
tm->tcpm_vals[TCP_METRIC_RTTVAR] = msval * USEC_PER_MSEC;
|
||||
tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH);
|
||||
tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND);
|
||||
tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING);
|
||||
@ -384,7 +381,7 @@ void tcp_update_metrics(struct sock *sk)
|
||||
dst_confirm(dst);
|
||||
|
||||
rcu_read_lock();
|
||||
if (icsk->icsk_backoff || !tp->srtt) {
|
||||
if (icsk->icsk_backoff || !tp->srtt_us) {
|
||||
/* This session failed to estimate rtt. Why?
|
||||
* Probably, no packets returned in time. Reset our
|
||||
* results.
|
||||
@ -399,8 +396,8 @@ void tcp_update_metrics(struct sock *sk)
|
||||
if (!tm)
|
||||
goto out_unlock;
|
||||
|
||||
rtt = tcp_metric_get_jiffies(tm, TCP_METRIC_RTT);
|
||||
m = rtt - tp->srtt;
|
||||
rtt = tcp_metric_get(tm, TCP_METRIC_RTT);
|
||||
m = rtt - tp->srtt_us;
|
||||
|
||||
/* If newly calculated rtt larger than stored one, store new
|
||||
* one. Otherwise, use EWMA. Remember, rtt overestimation is
|
||||
@ -408,10 +405,10 @@ void tcp_update_metrics(struct sock *sk)
|
||||
*/
|
||||
if (!tcp_metric_locked(tm, TCP_METRIC_RTT)) {
|
||||
if (m <= 0)
|
||||
rtt = tp->srtt;
|
||||
rtt = tp->srtt_us;
|
||||
else
|
||||
rtt -= (m >> 3);
|
||||
tcp_metric_set_msecs(tm, TCP_METRIC_RTT, rtt);
|
||||
tcp_metric_set(tm, TCP_METRIC_RTT, rtt);
|
||||
}
|
||||
|
||||
if (!tcp_metric_locked(tm, TCP_METRIC_RTTVAR)) {
|
||||
@ -422,16 +419,16 @@ void tcp_update_metrics(struct sock *sk)
|
||||
|
||||
/* Scale deviation to rttvar fixed point */
|
||||
m >>= 1;
|
||||
if (m < tp->mdev)
|
||||
m = tp->mdev;
|
||||
if (m < tp->mdev_us)
|
||||
m = tp->mdev_us;
|
||||
|
||||
var = tcp_metric_get_jiffies(tm, TCP_METRIC_RTTVAR);
|
||||
var = tcp_metric_get(tm, TCP_METRIC_RTTVAR);
|
||||
if (m >= var)
|
||||
var = m;
|
||||
else
|
||||
var -= (var - m) >> 2;
|
||||
|
||||
tcp_metric_set_msecs(tm, TCP_METRIC_RTTVAR, var);
|
||||
tcp_metric_set(tm, TCP_METRIC_RTTVAR, var);
|
||||
}
|
||||
|
||||
if (tcp_in_initial_slowstart(tp)) {
|
||||
@ -528,7 +525,7 @@ void tcp_init_metrics(struct sock *sk)
|
||||
tp->reordering = val;
|
||||
}
|
||||
|
||||
crtt = tcp_metric_get_jiffies(tm, TCP_METRIC_RTT);
|
||||
crtt = tcp_metric_get(tm, TCP_METRIC_RTT);
|
||||
rcu_read_unlock();
|
||||
reset:
|
||||
/* The initial RTT measurement from the SYN/SYN-ACK is not ideal
|
||||
@ -551,18 +548,20 @@ reset:
|
||||
* to low value, and then abruptly stops to do it and starts to delay
|
||||
* ACKs, wait for troubles.
|
||||
*/
|
||||
if (crtt > tp->srtt) {
|
||||
if (crtt > tp->srtt_us) {
|
||||
/* Set RTO like tcp_rtt_estimator(), but from cached RTT. */
|
||||
crtt >>= 3;
|
||||
crtt /= 8 * USEC_PER_MSEC;
|
||||
inet_csk(sk)->icsk_rto = crtt + max(2 * crtt, tcp_rto_min(sk));
|
||||
} else if (tp->srtt == 0) {
|
||||
} else if (tp->srtt_us == 0) {
|
||||
/* RFC6298: 5.7 We've failed to get a valid RTT sample from
|
||||
* 3WHS. This is most likely due to retransmission,
|
||||
* including spurious one. Reset the RTO back to 3secs
|
||||
* from the more aggressive 1sec to avoid more spurious
|
||||
* retransmission.
|
||||
*/
|
||||
tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_FALLBACK;
|
||||
tp->rttvar_us = jiffies_to_usecs(TCP_TIMEOUT_FALLBACK);
|
||||
tp->mdev_us = tp->mdev_max_us = tp->rttvar_us;
|
||||
|
||||
inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK;
|
||||
}
|
||||
/* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been
|
||||
@ -809,10 +808,26 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
|
||||
nest = nla_nest_start(msg, TCP_METRICS_ATTR_VALS);
|
||||
if (!nest)
|
||||
goto nla_put_failure;
|
||||
for (i = 0; i < TCP_METRIC_MAX + 1; i++) {
|
||||
if (!tm->tcpm_vals[i])
|
||||
for (i = 0; i < TCP_METRIC_MAX_KERNEL + 1; i++) {
|
||||
u32 val = tm->tcpm_vals[i];
|
||||
|
||||
if (!val)
|
||||
continue;
|
||||
if (nla_put_u32(msg, i + 1, tm->tcpm_vals[i]) < 0)
|
||||
if (i == TCP_METRIC_RTT) {
|
||||
if (nla_put_u32(msg, TCP_METRIC_RTT_US + 1,
|
||||
val) < 0)
|
||||
goto nla_put_failure;
|
||||
n++;
|
||||
val = max(val / 1000, 1U);
|
||||
}
|
||||
if (i == TCP_METRIC_RTTVAR) {
|
||||
if (nla_put_u32(msg, TCP_METRIC_RTTVAR_US + 1,
|
||||
val) < 0)
|
||||
goto nla_put_failure;
|
||||
n++;
|
||||
val = max(val / 1000, 1U);
|
||||
}
|
||||
if (nla_put_u32(msg, i + 1, val) < 0)
|
||||
goto nla_put_failure;
|
||||
n++;
|
||||
}
|
||||
|
@ -398,8 +398,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
|
||||
|
||||
tcp_init_wl(newtp, treq->rcv_isn);
|
||||
|
||||
newtp->srtt = 0;
|
||||
newtp->mdev = TCP_TIMEOUT_INIT;
|
||||
newtp->srtt_us = 0;
|
||||
newtp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT);
|
||||
newicsk->icsk_rto = TCP_TIMEOUT_INIT;
|
||||
|
||||
newtp->packets_out = 0;
|
||||
|
@ -866,11 +866,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
|
||||
if (clone_it) {
|
||||
const struct sk_buff *fclone = skb + 1;
|
||||
|
||||
/* If congestion control is doing timestamping, we must
|
||||
* take such a timestamp before we potentially clone/copy.
|
||||
*/
|
||||
if (icsk->icsk_ca_ops->flags & TCP_CONG_RTT_STAMP)
|
||||
__net_timestamp(skb);
|
||||
skb_mstamp_get(&skb->skb_mstamp);
|
||||
|
||||
if (unlikely(skb->fclone == SKB_FCLONE_ORIG &&
|
||||
fclone->fclone == SKB_FCLONE_CLONE))
|
||||
@ -1974,7 +1970,7 @@ bool tcp_schedule_loss_probe(struct sock *sk)
|
||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
u32 timeout, tlp_time_stamp, rto_time_stamp;
|
||||
u32 rtt = tp->srtt >> 3;
|
||||
u32 rtt = usecs_to_jiffies(tp->srtt_us >> 3);
|
||||
|
||||
if (WARN_ON(icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS))
|
||||
return false;
|
||||
@ -1996,7 +1992,7 @@ bool tcp_schedule_loss_probe(struct sock *sk)
|
||||
/* Schedule a loss probe in 2*RTT for SACK capable connections
|
||||
* in Open state, that are either limited by cwnd or application.
|
||||
*/
|
||||
if (sysctl_tcp_early_retrans < 3 || !tp->srtt || !tp->packets_out ||
|
||||
if (sysctl_tcp_early_retrans < 3 || !tp->srtt_us || !tp->packets_out ||
|
||||
!tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open)
|
||||
return false;
|
||||
|
||||
@ -3050,8 +3046,9 @@ void tcp_send_delayed_ack(struct sock *sk)
|
||||
* Do not use inet_csk(sk)->icsk_rto here, use results of rtt measurements
|
||||
* directly.
|
||||
*/
|
||||
if (tp->srtt) {
|
||||
int rtt = max(tp->srtt >> 3, TCP_DELACK_MIN);
|
||||
if (tp->srtt_us) {
|
||||
int rtt = max_t(int, usecs_to_jiffies(tp->srtt_us >> 3),
|
||||
TCP_DELACK_MIN);
|
||||
|
||||
if (rtt < max_ato)
|
||||
max_ato = rtt;
|
||||
|
@ -154,7 +154,7 @@ static void jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
|
||||
p->snd_wnd = tp->snd_wnd;
|
||||
p->rcv_wnd = tp->rcv_wnd;
|
||||
p->ssthresh = tcp_current_ssthresh(sk);
|
||||
p->srtt = tp->srtt >> 3;
|
||||
p->srtt = tp->srtt_us >> 3;
|
||||
|
||||
tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1);
|
||||
}
|
||||
|
@ -306,7 +306,6 @@ void tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
|
||||
EXPORT_SYMBOL_GPL(tcp_vegas_get_info);
|
||||
|
||||
static struct tcp_congestion_ops tcp_vegas __read_mostly = {
|
||||
.flags = TCP_CONG_RTT_STAMP,
|
||||
.init = tcp_vegas_init,
|
||||
.ssthresh = tcp_reno_ssthresh,
|
||||
.cong_avoid = tcp_vegas_cong_avoid,
|
||||
|
@ -203,7 +203,6 @@ static u32 tcp_veno_ssthresh(struct sock *sk)
|
||||
}
|
||||
|
||||
static struct tcp_congestion_ops tcp_veno __read_mostly = {
|
||||
.flags = TCP_CONG_RTT_STAMP,
|
||||
.init = tcp_veno_init,
|
||||
.ssthresh = tcp_veno_ssthresh,
|
||||
.cong_avoid = tcp_veno_cong_avoid,
|
||||
|
@ -227,7 +227,6 @@ static u32 tcp_yeah_ssthresh(struct sock *sk) {
|
||||
}
|
||||
|
||||
static struct tcp_congestion_ops tcp_yeah __read_mostly = {
|
||||
.flags = TCP_CONG_RTT_STAMP,
|
||||
.init = tcp_yeah_init,
|
||||
.ssthresh = tcp_yeah_ssthresh,
|
||||
.cong_avoid = tcp_yeah_cong_avoid,
|
||||
|
Loading…
Reference in New Issue
Block a user