Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_input.c
| Show First 20 Lines • Show All 2,606 Lines • ▼ Show 20 Lines | if (SEQ_LEQ(th->th_ack, tp->snd_una)) { | ||||
| break; | break; | ||||
| else if (!tcp_timer_active(tp, TT_REXMT)) | else if (!tcp_timer_active(tp, TT_REXMT)) | ||||
| tp->t_dupacks = 0; | tp->t_dupacks = 0; | ||||
| else if (++tp->t_dupacks > tcprexmtthresh || | else if (++tp->t_dupacks > tcprexmtthresh || | ||||
| IN_FASTRECOVERY(tp->t_flags)) { | IN_FASTRECOVERY(tp->t_flags)) { | ||||
| cc_ack_received(tp, th, nsegs, | cc_ack_received(tp, th, nsegs, | ||||
| CC_DUPACK); | CC_DUPACK); | ||||
| if (V_tcp_do_prr && | if (V_tcp_do_prr && | ||||
| IN_FASTRECOVERY(tp->t_flags) && | IN_FASTRECOVERY(tp->t_flags)) { | ||||
| (tp->t_flags & TF_SACK_PERMIT)) { | |||||
| tcp_do_prr_ack(tp, th, &to); | tcp_do_prr_ack(tp, th, &to); | ||||
| } else if ((tp->t_flags & TF_SACK_PERMIT) && | } else if ((tp->t_flags & TF_SACK_PERMIT) && | ||||
| (to.to_flags & TOF_SACK) && | (to.to_flags & TOF_SACK) && | ||||
| IN_FASTRECOVERY(tp->t_flags)) { | IN_FASTRECOVERY(tp->t_flags)) { | ||||
| int awnd; | int awnd; | ||||
| /* | /* | ||||
| * Compute the amount of data in flight first. | * Compute the amount of data in flight first. | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | enter_recovery: | ||||
| CC_DUPACK); | CC_DUPACK); | ||||
| tcp_timer_activate(tp, TT_REXMT, 0); | tcp_timer_activate(tp, TT_REXMT, 0); | ||||
| tp->t_rtttime = 0; | tp->t_rtttime = 0; | ||||
| if (V_tcp_do_prr) { | if (V_tcp_do_prr) { | ||||
| /* | /* | ||||
| * snd_ssthresh is already updated by | * snd_ssthresh is already updated by | ||||
| * cc_cong_signal. | * cc_cong_signal. | ||||
| */ | */ | ||||
| if ((tp->t_flags & TF_SACK_PERMIT) && | |||||
| (to.to_flags & TOF_SACK)) { | |||||
| tp->sackhint.prr_delivered = | tp->sackhint.prr_delivered = | ||||
| tp->sackhint.sacked_bytes; | tp->sackhint.sacked_bytes; | ||||
| } else { | |||||
| tp->sackhint.prr_delivered = | |||||
| imin(tp->snd_max - tp->snd_una, | |||||
| imin(INT_MAX / 65536, | |||||
jtl: Are you sure this can never wrap? | |||||
| tp->t_dupacks) * maxseg); | |||||
| } | |||||
| tp->sackhint.recover_fs = max(1, | tp->sackhint.recover_fs = max(1, | ||||
| tp->snd_nxt - tp->snd_una); | tp->snd_nxt - tp->snd_una); | ||||
| } | } | ||||
| if ((tp->t_flags & TF_SACK_PERMIT) && | if ((tp->t_flags & TF_SACK_PERMIT) && | ||||
| (to.to_flags & TOF_SACK)) { | (to.to_flags & TOF_SACK)) { | ||||
| TCPSTAT_INC( | TCPSTAT_INC( | ||||
| tcps_sack_recovery_episode); | tcps_sack_recovery_episode); | ||||
| tp->snd_recover = tp->snd_nxt; | tp->snd_recover = tp->snd_nxt; | ||||
| ▲ Show 20 Lines • Show All 1,261 Lines • ▼ Show 20 Lines | tcp_do_prr_ack(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to) | ||||
| INP_WLOCK_ASSERT(tp->t_inpcb); | INP_WLOCK_ASSERT(tp->t_inpcb); | ||||
| /* | /* | ||||
| * Compute the amount of data that this ACK is indicating | * Compute the amount of data that this ACK is indicating | ||||
| * (del_data) and an estimate of how many bytes are in the | * (del_data) and an estimate of how many bytes are in the | ||||
| * network. | * network. | ||||
| */ | */ | ||||
| if (((tp->t_flags & TF_SACK_PERMIT) && | |||||
| (to->to_flags & TOF_SACK)) || | |||||
| (IN_CONGRECOVERY(tp->t_flags) && | |||||
| !IN_FASTRECOVERY(tp->t_flags))) { | |||||
| del_data = tp->sackhint.delivered_data; | del_data = tp->sackhint.delivered_data; | ||||
| if (V_tcp_do_newsack) | if (V_tcp_do_newsack) | ||||
| pipe = tcp_compute_pipe(tp); | pipe = tcp_compute_pipe(tp); | ||||
| else | else | ||||
| pipe = (tp->snd_nxt - tp->snd_fack) + tp->sackhint.sack_bytes_rexmit; | pipe = (tp->snd_nxt - tp->snd_fack) + | ||||
| tp->sackhint.sack_bytes_rexmit; | |||||
| } else { | |||||
| if (tp->sackhint.prr_delivered < (tcprexmtthresh * maxseg + | |||||
| tp->snd_recover - tp->snd_una)) | |||||
| del_data = maxseg; | |||||
| pipe = imax(0, tp->snd_max - tp->snd_una - | |||||
| imin(INT_MAX / 65536, tp->t_dupacks) * maxseg); | |||||
Not Done Inline ActionsAgain, can t_dupacks * maxseg never wrap? jtl: Again, can t_dupacks * maxseg never wrap? | |||||
| } | |||||
| tp->sackhint.prr_delivered += del_data; | tp->sackhint.prr_delivered += del_data; | ||||
| /* | /* | ||||
| * Proportional Rate Reduction | * Proportional Rate Reduction | ||||
| */ | */ | ||||
| if (pipe >= tp->snd_ssthresh) { | if (pipe >= tp->snd_ssthresh) { | ||||
| if (tp->sackhint.recover_fs == 0) | if (tp->sackhint.recover_fs == 0) | ||||
| tp->sackhint.recover_fs = | tp->sackhint.recover_fs = | ||||
| imax(1, tp->snd_nxt - tp->snd_una); | imax(1, tp->snd_nxt - tp->snd_una); | ||||
| snd_cnt = howmany((long)tp->sackhint.prr_delivered * | snd_cnt = howmany((long)tp->sackhint.prr_delivered * | ||||
| tp->snd_ssthresh, tp->sackhint.recover_fs) - | tp->snd_ssthresh, tp->sackhint.recover_fs) - | ||||
| tp->sackhint.prr_out; | tp->sackhint.prr_out; | ||||
| } else { | } else { | ||||
| if (V_tcp_do_prr_conservative) | if (V_tcp_do_prr_conservative || (del_data == 0)) | ||||
| limit = tp->sackhint.prr_delivered - | limit = tp->sackhint.prr_delivered - | ||||
| tp->sackhint.prr_out; | tp->sackhint.prr_out; | ||||
| else | else | ||||
| limit = imax(tp->sackhint.prr_delivered - | limit = imax(tp->sackhint.prr_delivered - | ||||
| tp->sackhint.prr_out, del_data) + | tp->sackhint.prr_out, del_data) + | ||||
| maxseg; | maxseg; | ||||
| snd_cnt = imin((tp->snd_ssthresh - pipe), limit); | snd_cnt = imin((tp->snd_ssthresh - pipe), limit); | ||||
| } | } | ||||
| snd_cnt = imax(snd_cnt, 0) / maxseg; | snd_cnt = imax(snd_cnt, 0) / maxseg; | ||||
| /* | /* | ||||
| * Send snd_cnt new data into the network in response to this ack. | * Send snd_cnt new data into the network in response to this ack. | ||||
| * If there is going to be a SACK retransmission, adjust snd_cwnd | * If there is going to be a SACK retransmission, adjust snd_cwnd | ||||
| * accordingly. | * accordingly. | ||||
| */ | */ | ||||
| if (IN_FASTRECOVERY(tp->t_flags)) { | if (IN_FASTRECOVERY(tp->t_flags)) { | ||||
| tp->snd_cwnd = imax(maxseg, tp->snd_nxt - tp->snd_recover + | if ((tp->t_flags & TF_SACK_PERMIT) && | ||||
| tp->sackhint.sack_bytes_rexmit + (snd_cnt * maxseg)); | (to->to_flags & TOF_SACK)) { | ||||
| tp->snd_cwnd = tp->snd_nxt - tp->snd_recover + | |||||
| tp->sackhint.sack_bytes_rexmit + | |||||
| (snd_cnt * maxseg); | |||||
| } else { | |||||
| tp->snd_cwnd = (tp->snd_max - tp->snd_una) + | |||||
| (snd_cnt * maxseg); | |||||
| } | |||||
| } else if (IN_CONGRECOVERY(tp->t_flags)) | } else if (IN_CONGRECOVERY(tp->t_flags)) | ||||
| tp->snd_cwnd = imax(maxseg, pipe - del_data + | tp->snd_cwnd = pipe - del_data + (snd_cnt * maxseg); | ||||
| (snd_cnt * maxseg)); | tp->snd_cwnd = imax(maxseg, tp->snd_cwnd); | ||||
| } | } | ||||
| /* | /* | ||||
| * On a partial ack arrives, force the retransmission of the | * On a partial ack arrives, force the retransmission of the | ||||
| * next unacknowledged segment. Do not clear tp->t_dupacks. | * next unacknowledged segment. Do not clear tp->t_dupacks. | ||||
| * By setting snd_nxt to ti_ack, this forces retransmission timer to | * By setting snd_nxt to ti_ack, this forces retransmission timer to | ||||
| * be started again. | * be started again. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 67 Lines • Show Last 20 Lines | |||||
Are you sure this can never wrap?