Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_input.c
Show First 20 Lines • Show All 1,882 Lines • ▼ Show 20 Lines | #endif | ||||
*/ | */ | ||||
#ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
if (so->so_options & SO_DEBUG) | if (so->so_options & SO_DEBUG) | ||||
tcp_trace(TA_INPUT, ostate, tp, | tcp_trace(TA_INPUT, ostate, tp, | ||||
(void *)tcp_saveipgen, | (void *)tcp_saveipgen, | ||||
&tcp_savetcp, 0); | &tcp_savetcp, 0); | ||||
#endif | #endif | ||||
TCP_PROBE3(debug__input, tp, th, m); | TCP_PROBE3(debug__input, tp, th, m); | ||||
/* | |||||
* Clear t_acktime if remote side has ACKd | |||||
* all data in the socket buffer. | |||||
* Otherwise, update t_acktime if we received | |||||
* a sufficiently large ACK. | |||||
*/ | |||||
if (sbavail(&so->so_snd) == 0) | |||||
tp->t_acktime = 0; | |||||
else if (acked > 1) | |||||
tp->t_acktime = ticks; | |||||
if (tp->snd_una == tp->snd_max) | if (tp->snd_una == tp->snd_max) | ||||
tcp_timer_activate(tp, TT_REXMT, 0); | tcp_timer_activate(tp, TT_REXMT, 0); | ||||
else if (!tcp_timer_active(tp, TT_PERSIST)) | else if (!tcp_timer_active(tp, TT_PERSIST)) | ||||
tcp_timer_activate(tp, TT_REXMT, | tcp_timer_activate(tp, TT_REXMT, | ||||
tp->t_rxtcur); | TP_RXTCUR(tp)); | ||||
sowwakeup(so); | sowwakeup(so); | ||||
if (sbavail(&so->so_snd)) | if (sbavail(&so->so_snd)) | ||||
(void) tcp_output(tp); | (void) tcp_output(tp); | ||||
goto check_delack; | goto check_delack; | ||||
} | } | ||||
} else if (th->th_ack == tp->snd_una && | } else if (th->th_ack == tp->snd_una && | ||||
tlen <= sbspace(&so->so_rcv)) { | tlen <= sbspace(&so->so_rcv)) { | ||||
int newsize = 0; /* automatic sockbuf scaling */ | int newsize = 0; /* automatic sockbuf scaling */ | ||||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Received <SYN,ACK> in SYN_SENT[*] state. | * Received <SYN,ACK> in SYN_SENT[*] state. | ||||
* Transitions: | * Transitions: | ||||
* SYN_SENT --> ESTABLISHED | * SYN_SENT --> ESTABLISHED | ||||
* SYN_SENT* --> FIN_WAIT_1 | * SYN_SENT* --> FIN_WAIT_1 | ||||
*/ | */ | ||||
tp->t_starttime = ticks; | tp->t_starttime = ticks; | ||||
if (tp->t_flags & TF_NEEDFIN) { | if (tp->t_flags & TF_NEEDFIN) { | ||||
tp->t_acktime = ticks; | |||||
tcp_state_change(tp, TCPS_FIN_WAIT_1); | tcp_state_change(tp, TCPS_FIN_WAIT_1); | ||||
tp->t_flags &= ~TF_NEEDFIN; | tp->t_flags &= ~TF_NEEDFIN; | ||||
thflags &= ~TH_SYN; | thflags &= ~TH_SYN; | ||||
} else { | } else { | ||||
tcp_state_change(tp, TCPS_ESTABLISHED); | tcp_state_change(tp, TCPS_ESTABLISHED); | ||||
TCP_PROBE5(connect__established, NULL, tp, | TCP_PROBE5(connect__established, NULL, tp, | ||||
m, tp, th); | m, tp, th); | ||||
cc_conn_init(tp); | cc_conn_init(tp); | ||||
▲ Show 20 Lines • Show All 368 Lines • ▼ Show 20 Lines | case TCPS_SYN_RECEIVED: | ||||
* SYN-RECEIVED* -> FIN-WAIT-1 | * SYN-RECEIVED* -> FIN-WAIT-1 | ||||
*/ | */ | ||||
tp->t_starttime = ticks; | tp->t_starttime = ticks; | ||||
if (IS_FASTOPEN(tp->t_flags) && tp->t_tfo_pending) { | if (IS_FASTOPEN(tp->t_flags) && tp->t_tfo_pending) { | ||||
tcp_fastopen_decrement_counter(tp->t_tfo_pending); | tcp_fastopen_decrement_counter(tp->t_tfo_pending); | ||||
tp->t_tfo_pending = NULL; | tp->t_tfo_pending = NULL; | ||||
} | } | ||||
if (tp->t_flags & TF_NEEDFIN) { | if (tp->t_flags & TF_NEEDFIN) { | ||||
tp->t_acktime = ticks; | |||||
tcp_state_change(tp, TCPS_FIN_WAIT_1); | tcp_state_change(tp, TCPS_FIN_WAIT_1); | ||||
tp->t_flags &= ~TF_NEEDFIN; | tp->t_flags &= ~TF_NEEDFIN; | ||||
} else { | } else { | ||||
tcp_state_change(tp, TCPS_ESTABLISHED); | tcp_state_change(tp, TCPS_ESTABLISHED); | ||||
TCP_PROBE5(accept__established, NULL, tp, | TCP_PROBE5(accept__established, NULL, tp, | ||||
m, tp, th); | m, tp, th); | ||||
/* | /* | ||||
* TFO connections call cc_conn_init() during SYN | * TFO connections call cc_conn_init() during SYN | ||||
▲ Show 20 Lines • Show All 430 Lines • ▼ Show 20 Lines | if ((to.to_flags & TOF_TS) != 0 && to.to_tsecr) { | ||||
tp->t_rttlow = t; | tp->t_rttlow = t; | ||||
tcp_xmit_timer(tp, TCP_TS_TO_TICKS(t) + 1); | tcp_xmit_timer(tp, TCP_TS_TO_TICKS(t) + 1); | ||||
} else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) { | } else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) { | ||||
if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime) | if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime) | ||||
tp->t_rttlow = ticks - tp->t_rtttime; | tp->t_rttlow = ticks - tp->t_rtttime; | ||||
tcp_xmit_timer(tp, ticks - tp->t_rtttime); | tcp_xmit_timer(tp, ticks - tp->t_rtttime); | ||||
} | } | ||||
SOCKBUF_LOCK(&so->so_snd); | |||||
/* | /* | ||||
* Clear t_acktime if remote side has ACKd all data in the | |||||
* socket buffer and FIN (if applicable). | |||||
* Otherwise, update t_acktime if we received a sufficiently | |||||
* large ACK. | |||||
*/ | |||||
if ((tp->t_state <= TCPS_CLOSE_WAIT && | |||||
acked == sbavail(&so->so_snd)) || | |||||
acked > sbavail(&so->so_snd)) | |||||
tp->t_acktime = 0; | |||||
else if (acked > 1) | |||||
tp->t_acktime = ticks; | |||||
/* | |||||
* If all outstanding data is acked, stop retransmit | * If all outstanding data is acked, stop retransmit | ||||
* timer and remember to restart (more output or persist). | * timer and remember to restart (more output or persist). | ||||
* If there is more data to be acked, restart retransmit | * If there is more data to be acked, restart retransmit | ||||
* timer, using current (possibly backed-off) value. | * timer, using current (possibly backed-off) value. | ||||
*/ | */ | ||||
if (th->th_ack == tp->snd_max) { | if (th->th_ack == tp->snd_max) { | ||||
tcp_timer_activate(tp, TT_REXMT, 0); | tcp_timer_activate(tp, TT_REXMT, 0); | ||||
needoutput = 1; | needoutput = 1; | ||||
} else if (!tcp_timer_active(tp, TT_PERSIST)) | } else if (!tcp_timer_active(tp, TT_PERSIST)) | ||||
tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); | tcp_timer_activate(tp, TT_REXMT, TP_RXTCUR(tp)); | ||||
/* | /* | ||||
* If no data (only SYN) was ACK'd, | * If no data (only SYN) was ACK'd, | ||||
* skip rest of ACK processing. | * skip rest of ACK processing. | ||||
*/ | */ | ||||
if (acked == 0) | if (acked == 0) { | ||||
SOCKBUF_UNLOCK(&so->so_snd); | |||||
goto step6; | goto step6; | ||||
} | |||||
/* | /* | ||||
* Let the congestion control algorithm update congestion | * Let the congestion control algorithm update congestion | ||||
* control related information. This typically means increasing | * control related information. This typically means increasing | ||||
* the congestion window. | * the congestion window. | ||||
*/ | */ | ||||
cc_ack_received(tp, th, nsegs, CC_ACK); | cc_ack_received(tp, th, nsegs, CC_ACK); | ||||
SOCKBUF_LOCK(&so->so_snd); | |||||
if (acked > sbavail(&so->so_snd)) { | if (acked > sbavail(&so->so_snd)) { | ||||
if (tp->snd_wnd >= sbavail(&so->so_snd)) | if (tp->snd_wnd >= sbavail(&so->so_snd)) | ||||
tp->snd_wnd -= sbavail(&so->so_snd); | tp->snd_wnd -= sbavail(&so->so_snd); | ||||
else | else | ||||
tp->snd_wnd = 0; | tp->snd_wnd = 0; | ||||
mfree = sbcut_locked(&so->so_snd, | mfree = sbcut_locked(&so->so_snd, | ||||
(int)sbavail(&so->so_snd)); | (int)sbavail(&so->so_snd)); | ||||
ourfinisacked = 1; | ourfinisacked = 1; | ||||
▲ Show 20 Lines • Show All 1,152 Lines • Show Last 20 Lines |