X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/fe8ab488e9161c46dd9885d58fc52996dc0249ff..cc8bc92ae4a8e9f1a1ab61bf83d34ad8150b3405:/bsd/netinet/tcp_cubic.c diff --git a/bsd/netinet/tcp_cubic.c b/bsd/netinet/tcp_cubic.c index 7e2d00b07..c9ce59c04 100644 --- a/bsd/netinet/tcp_cubic.c +++ b/bsd/netinet/tcp_cubic.c @@ -89,20 +89,14 @@ const float tcp_cubic_backoff = 0.2; /* multiplicative decrease factor */ const float tcp_cubic_coeff = 0.4; const float tcp_cubic_fast_convergence_factor = 0.875; -static int tcp_cubic_tcp_friendliness = 0; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, cubic_tcp_friendliness, - CTLFLAG_RW | CTLFLAG_LOCKED, &tcp_cubic_tcp_friendliness, 0, - "Enable TCP friendliness"); +SYSCTL_SKMEM_TCP_INT(OID_AUTO, cubic_tcp_friendliness, CTLFLAG_RW | CTLFLAG_LOCKED, + static int, tcp_cubic_tcp_friendliness, 0, "Enable TCP friendliness"); -static int tcp_cubic_fast_convergence = 0; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, cubic_fast_convergence, - CTLFLAG_RW | CTLFLAG_LOCKED, &tcp_cubic_fast_convergence, 0, - "Enable fast convergence"); +SYSCTL_SKMEM_TCP_INT(OID_AUTO, cubic_fast_convergence, CTLFLAG_RW | CTLFLAG_LOCKED, + static int, tcp_cubic_fast_convergence, 0, "Enable fast convergence"); -static int tcp_cubic_use_minrtt = 0; -SYSCTL_INT(_net_inet_tcp, OID_AUTO, cubic_use_minrtt, - CTLFLAG_RW | CTLFLAG_LOCKED, &tcp_cubic_use_minrtt, 0, - "use a min of 5 sec rtt"); +SYSCTL_SKMEM_TCP_INT(OID_AUTO, cubic_use_minrtt, CTLFLAG_RW | CTLFLAG_LOCKED, + static int, tcp_cubic_use_minrtt, 0, "use a min of 5 sec rtt"); static int tcp_cubic_init(struct tcpcb *tp) { @@ -130,6 +124,11 @@ static void tcp_cubic_cwnd_init_or_reset(struct tcpcb *tp) tcp_cubic_clear_state(tp); tcp_cc_cwnd_init_or_reset(tp); + tp->t_pipeack = 0; + tcp_clear_pipeack_state(tp); + + /* Start counting bytes for RFC 3465 again */ + tp->t_bytes_acked = 0; /* * slow start threshold could get initialized to a lower value @@ -144,9 +143,6 @@ static void tcp_cubic_cwnd_init_or_reset(struct tcpcb *tp) /* Initialize cubic last max to be same as ssthresh */ tp->t_ccstate->cub_last_max = tp->snd_ssthresh; - - /* If stretch ack was auto-disabled, re-evaluate it */ - tcp_cc_after_idle_stretchack(tp); } /* @@ -161,8 +157,10 @@ tcp_cubic_update(struct tcpcb *tp, u_int32_t rtt) float K, var; u_int32_t elapsed_time, win; - VERIFY(tp->t_ccstate->cub_last_max > 0); win = min(tp->snd_cwnd, tp->snd_wnd); + if (tp->t_ccstate->cub_last_max == 0) + tp->t_ccstate->cub_last_max = tp->snd_ssthresh; + if (tp->t_ccstate->cub_epoch_start == 0) { /* * This is the beginning of a new epoch, initialize some of @@ -210,7 +208,7 @@ tcp_cubic_update(struct tcpcb *tp, u_int32_t rtt) var = (elapsed_time - tp->t_ccstate->cub_epoch_period) / TCP_RETRANSHZ; var = var * var * var * (tcp_cubic_coeff * tp->t_maxseg); - tp->t_ccstate->cub_target_win = tp->t_ccstate->cub_origin_point + var; + tp->t_ccstate->cub_target_win = (u_int32_t)(tp->t_ccstate->cub_origin_point + var); return (tp->t_ccstate->cub_target_win); } @@ -271,6 +269,10 @@ tcp_cubic_congestion_avd(struct tcpcb *tp, struct tcphdr *th) { u_int32_t cubic_target_win, tcp_win, rtt; + /* Do not increase congestion window in non-validated phase */ + if (tcp_cc_is_cwnd_nonvalidated(tp) != 0) + return; + tp->t_bytes_acked += BYTES_ACKED(th, tp); rtt = get_base_rtt(tp); @@ -318,6 +320,10 @@ tcp_cubic_congestion_avd(struct tcpcb *tp, struct tcphdr *th) static void tcp_cubic_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) { + /* Do not increase the congestion window in non-validated phase */ + if (tcp_cc_is_cwnd_nonvalidated(tp) != 0) + return; + if (tp->snd_cwnd >= tp->snd_ssthresh) { /* Congestion avoidance phase */ tcp_cubic_congestion_avd(tp, th); @@ -327,6 +333,7 @@ tcp_cubic_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) * by RFC 3465 section 2.3 */ uint32_t acked, abc_lim, incr; + acked = BYTES_ACKED(th, tp); abc_lim = (tcp_do_rfc3465_lim2 && tp->snd_nxt == tp->snd_max) ? @@ -342,7 +349,7 @@ tcp_cubic_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) static void tcp_cubic_pre_fr(struct tcpcb *tp) { - uint32_t win, avg; + u_int32_t win, avg; int32_t dev; tp->t_ccstate->cub_epoch_start = 0; tp->t_ccstate->cub_tcp_win = 0; @@ -350,6 +357,12 @@ tcp_cubic_pre_fr(struct tcpcb *tp) tp->t_ccstate->cub_tcp_bytes_acked = 0; win = min(tp->snd_cwnd, tp->snd_wnd); + if (tp->t_flagsext & TF_CWND_NONVALIDATED) { + tp->t_lossflightsize = tp->snd_max - tp->snd_una; + win = (max(tp->t_pipeack, tp->t_lossflightsize)) >> 1; + } else { + tp->t_lossflightsize = 0; + } /* * Note the congestion window at which packet loss occurred as * cub_last_max. @@ -363,8 +376,8 @@ tcp_cubic_pre_fr(struct tcpcb *tp) */ if (win < tp->t_ccstate->cub_last_max && tcp_cubic_fast_convergence == 1) - tp->t_ccstate->cub_last_max = win * - tcp_cubic_fast_convergence_factor; + tp->t_ccstate->cub_last_max = (u_int32_t)(win * + tcp_cubic_fast_convergence_factor); else tp->t_ccstate->cub_last_max = win; @@ -410,7 +423,7 @@ tcp_cubic_pre_fr(struct tcpcb *tp) } /* Backoff congestion window by tcp_cubic_backoff factor */ - win = win - (win * tcp_cubic_backoff); + win = (u_int32_t)(win - (win * tcp_cubic_backoff)); win = (win / tp->t_maxseg); if (win < 2) win = 2; @@ -425,6 +438,27 @@ tcp_cubic_post_fr(struct tcpcb *tp, struct tcphdr *th) if (SEQ_LEQ(th->th_ack, tp->snd_max)) flight_size = tp->snd_max - th->th_ack; + + if (SACK_ENABLED(tp) && tp->t_lossflightsize > 0) { + u_int32_t total_rxt_size = 0, ncwnd; + /* + * When SACK is enabled, the number of retransmitted bytes + * can be counted more accurately. + */ + total_rxt_size = tcp_rxtseg_total_size(tp); + ncwnd = max(tp->t_pipeack, tp->t_lossflightsize); + if (total_rxt_size <= ncwnd) { + ncwnd = ncwnd - total_rxt_size; + } + + /* + * To avoid sending a large burst at the end of recovery + * set a max limit on ncwnd + */ + ncwnd = min(ncwnd, (tp->t_maxseg << 6)); + ncwnd = ncwnd >> 1; + flight_size = max(ncwnd, flight_size); + } /* * Complete ack. The current window was inflated for fast recovery. * It has to be deflated post recovery. @@ -448,6 +482,16 @@ static void tcp_cubic_after_timeout(struct tcpcb *tp) { VERIFY(tp->t_ccstate != NULL); + + /* + * Avoid adjusting congestion window due to SYN retransmissions. + * If more than one byte (SYN) is outstanding then it is still + * needed to adjust the window. + */ + if (tp->t_state < TCPS_ESTABLISHED && + ((int)(tp->snd_max - tp->snd_una) <= 1)) + return; + if (!IN_FASTRECOVERY(tp)) { tcp_cubic_clear_state(tp); tcp_cubic_pre_fr(tp); @@ -477,8 +521,6 @@ tcp_cubic_switch_cc(struct tcpcb *tp, uint16_t old_cc_index) { #pragma unused(old_cc_index) tcp_cubic_cwnd_init_or_reset(tp); - /* Start counting bytes for RFC 3465 again */ - tp->t_bytes_acked = 0; OSIncrementAtomic((volatile SInt32 *)&tcp_cc_cubic.num_sockets); }