diff options
Diffstat (limited to 'net/ipv4/tcp_cubic.c')
| -rw-r--r-- | net/ipv4/tcp_cubic.c | 74 | 
1 files changed, 51 insertions, 23 deletions
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 71d5f2f29fa..a9bd8a4828a 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -39,7 +39,7 @@  /* Number of delay samples for detecting the increase of delay */  #define HYSTART_MIN_SAMPLES	8 -#define HYSTART_DELAY_MIN	(2U<<3) +#define HYSTART_DELAY_MIN	(4U<<3)  #define HYSTART_DELAY_MAX	(16U<<3)  #define HYSTART_DELAY_THRESH(x)	clamp(x, HYSTART_DELAY_MIN, HYSTART_DELAY_MAX) @@ -52,6 +52,7 @@ static int tcp_friendliness __read_mostly = 1;  static int hystart __read_mostly = 1;  static int hystart_detect __read_mostly = HYSTART_ACK_TRAIN | HYSTART_DELAY;  static int hystart_low_window __read_mostly = 16; +static int hystart_ack_delta __read_mostly = 2;  static u32 cube_rtt_scale __read_mostly;  static u32 beta_scale __read_mostly; @@ -75,6 +76,8 @@ MODULE_PARM_DESC(hystart_detect, "hyrbrid slow start detection mechanisms"  		 " 1: packet-train 2: delay 3: both packet-train and delay");  module_param(hystart_low_window, int, 0644);  MODULE_PARM_DESC(hystart_low_window, "lower bound cwnd for hybrid slow start"); +module_param(hystart_ack_delta, int, 0644); +MODULE_PARM_DESC(hystart_ack_delta, "spacing between ack's indicating train (msecs)");  /* BIC TCP Parameters */  struct bictcp { @@ -85,17 +88,18 @@ struct bictcp {  	u32	last_time;	/* time when updated last_cwnd */  	u32	bic_origin_point;/* origin point of bic function */  	u32	bic_K;		/* time to origin point from the beginning of the current epoch */ -	u32	delay_min;	/* min delay */ +	u32	delay_min;	/* min delay (msec << 3) */  	u32	epoch_start;	/* beginning of an epoch */  	u32	ack_cnt;	/* number of acks */  	u32	tcp_cwnd;	/* estimated tcp cwnd */  #define ACK_RATIO_SHIFT	4 +#define ACK_RATIO_LIMIT (32u << ACK_RATIO_SHIFT)  	u16	delayed_ack;	/* estimate the ratio of Packets/ACKs << 4 */  	u8	sample_cnt;	/* number of samples to decide curr_rtt */  	u8	found;		/* the exit point is found? */  	u32	round_start;	/* beginning of each round */  	u32	end_seq;	/* end_seq of the round */ -	u32	last_jiffies;	/* last time when the ACK spacing is close */ +	u32	last_ack;	/* last time when the ACK spacing is close */  	u32	curr_rtt;	/* the minimum rtt of current round */  }; @@ -103,7 +107,6 @@ static inline void bictcp_reset(struct bictcp *ca)  {  	ca->cnt = 0;  	ca->last_max_cwnd = 0; -	ca->loss_cwnd = 0;  	ca->last_cwnd = 0;  	ca->last_time = 0;  	ca->bic_origin_point = 0; @@ -116,12 +119,21 @@ static inline void bictcp_reset(struct bictcp *ca)  	ca->found = 0;  } +static inline u32 bictcp_clock(void) +{ +#if HZ < 1000 +	return ktime_to_ms(ktime_get_real()); +#else +	return jiffies_to_msecs(jiffies); +#endif +} +  static inline void bictcp_hystart_reset(struct sock *sk)  {  	struct tcp_sock *tp = tcp_sk(sk);  	struct bictcp *ca = inet_csk_ca(sk); -	ca->round_start = ca->last_jiffies = jiffies; +	ca->round_start = ca->last_ack = bictcp_clock();  	ca->end_seq = tp->snd_nxt;  	ca->curr_rtt = 0;  	ca->sample_cnt = 0; @@ -129,7 +141,10 @@ static inline void bictcp_hystart_reset(struct sock *sk)  static void bictcp_init(struct sock *sk)  { -	bictcp_reset(inet_csk_ca(sk)); +	struct bictcp *ca = inet_csk_ca(sk); + +	bictcp_reset(ca); +	ca->loss_cwnd = 0;  	if (hystart)  		bictcp_hystart_reset(sk); @@ -191,8 +206,8 @@ static u32 cubic_root(u64 a)   */  static inline void bictcp_update(struct bictcp *ca, u32 cwnd)  { -	u64 offs; -	u32 delta, t, bic_target, max_cnt; +	u32 delta, bic_target, max_cnt; +	u64 offs, t;  	ca->ack_cnt++;	/* count the number of ACKs */ @@ -235,9 +250,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)  	 * if the cwnd < 1 million packets !!!  	 */ +	t = (s32)(tcp_time_stamp - ca->epoch_start); +	t += msecs_to_jiffies(ca->delay_min >> 3);  	/* change the unit from HZ to bictcp_HZ */ -	t = ((tcp_time_stamp + (ca->delay_min>>3) - ca->epoch_start) -	     << BICTCP_HZ) / HZ; +	t <<= BICTCP_HZ; +	do_div(t, HZ);  	if (t < ca->bic_K)		/* t - K */  		offs = ca->bic_K - t; @@ -258,6 +275,13 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)  		ca->cnt = 100 * cwnd;              /* very small increment*/  	} +	/* +	 * The initial growth of cubic function may be too conservative +	 * when the available bandwidth is still unknown. +	 */ +	if (ca->last_max_cwnd == 0 && ca->cnt > 20) +		ca->cnt = 20;	/* increase cwnd 5% per RTT */ +  	/* TCP Friendly */  	if (tcp_friendliness) {  		u32 scale = beta_scale; @@ -280,18 +304,18 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)  		ca->cnt = 1;  } -static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) +static void bictcp_cong_avoid(struct sock *sk, u32 ack, u32 acked)  {  	struct tcp_sock *tp = tcp_sk(sk);  	struct bictcp *ca = inet_csk_ca(sk); -	if (!tcp_is_cwnd_limited(sk, in_flight)) +	if (!tcp_is_cwnd_limited(sk))  		return;  	if (tp->snd_cwnd <= tp->snd_ssthresh) {  		if (hystart && after(ack, ca->end_seq))  			bictcp_hystart_reset(sk); -		tcp_slow_start(tp); +		tcp_slow_start(tp, acked);  	} else {  		bictcp_update(ca, tp->snd_cwnd);  		tcp_cong_avoid_ai(tp, ca->cnt); @@ -322,7 +346,7 @@ static u32 bictcp_undo_cwnd(struct sock *sk)  {  	struct bictcp *ca = inet_csk_ca(sk); -	return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd); +	return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);  }  static void bictcp_state(struct sock *sk, u8 new_state) @@ -339,12 +363,12 @@ static void hystart_update(struct sock *sk, u32 delay)  	struct bictcp *ca = inet_csk_ca(sk);  	if (!(ca->found & hystart_detect)) { -		u32 curr_jiffies = jiffies; +		u32 now = bictcp_clock();  		/* first detection parameter - ack-train detection */ -		if (curr_jiffies - ca->last_jiffies <= msecs_to_jiffies(2)) { -			ca->last_jiffies = curr_jiffies; -			if (curr_jiffies - ca->round_start >= ca->delay_min>>4) +		if ((s32)(now - ca->last_ack) <= hystart_ack_delta) { +			ca->last_ack = now; +			if ((s32)(now - ca->round_start) > ca->delay_min >> 4)  				ca->found |= HYSTART_ACK_TRAIN;  		} @@ -379,8 +403,12 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)  	u32 delay;  	if (icsk->icsk_ca_state == TCP_CA_Open) { -		cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT; -		ca->delayed_ack += cnt; +		u32 ratio = ca->delayed_ack; + +		ratio -= ca->delayed_ack >> ACK_RATIO_SHIFT; +		ratio += cnt; + +		ca->delayed_ack = clamp(ratio, 1U, ACK_RATIO_LIMIT);  	}  	/* Some calls are for duplicates without timetamps */ @@ -388,10 +416,10 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)  		return;  	/* Discard delay samples right after fast recovery */ -	if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ) +	if (ca->epoch_start && (s32)(tcp_time_stamp - ca->epoch_start) < HZ)  		return; -	delay = usecs_to_jiffies(rtt_us) << 3; +	delay = (rtt_us << 3) / USEC_PER_MSEC;  	if (delay == 0)  		delay = 1; @@ -405,7 +433,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)  		hystart_update(sk, delay);  } -static struct tcp_congestion_ops cubictcp = { +static struct tcp_congestion_ops cubictcp __read_mostly = {  	.init		= bictcp_init,  	.ssthresh	= bictcp_recalc_ssthresh,  	.cong_avoid	= bictcp_cong_avoid,  | 
