Changeset View
Changeset View
Standalone View
Standalone View
stable/11/sys/netinet/tcp_input.c
Show First 20 Lines • Show All 1,754 Lines • ▼ Show 20 Lines | #endif | ||||
* be TH_NEEDSYN. | * be TH_NEEDSYN. | ||||
*/ | */ | ||||
if (tp->t_state == TCPS_ESTABLISHED && | if (tp->t_state == TCPS_ESTABLISHED && | ||||
th->th_seq == tp->rcv_nxt && | th->th_seq == tp->rcv_nxt && | ||||
(thflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && | (thflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && | ||||
tp->snd_nxt == tp->snd_max && | tp->snd_nxt == tp->snd_max && | ||||
tiwin && tiwin == tp->snd_wnd && | tiwin && tiwin == tp->snd_wnd && | ||||
((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) && | ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) && | ||||
LIST_EMPTY(&tp->t_segq) && | SEGQ_EMPTY(tp) && | ||||
((to.to_flags & TOF_TS) == 0 || | ((to.to_flags & TOF_TS) == 0 || | ||||
TSTMP_GEQ(to.to_tsval, tp->ts_recent)) ) { | TSTMP_GEQ(to.to_tsval, tp->ts_recent)) ) { | ||||
/* | /* | ||||
* If last ACK falls within this segment's sequence numbers, | * If last ACK falls within this segment's sequence numbers, | ||||
* record the timestamp. | * record the timestamp. | ||||
* NOTE that the test is modified according to the latest | * NOTE that the test is modified according to the latest | ||||
* proposal of the tcplw@cray.com list (Braden 1993/04/26). | * proposal of the tcplw@cray.com list (Braden 1993/04/26). | ||||
▲ Show 20 Lines • Show All 696 Lines • ▼ Show 20 Lines | #endif | ||||
cc_conn_init(tp); | cc_conn_init(tp); | ||||
tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); | tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); | ||||
} | } | ||||
/* | /* | ||||
* If segment contains data or ACK, will call tcp_reass() | * If segment contains data or ACK, will call tcp_reass() | ||||
* later; if not, do so now to pass queued data to user. | * later; if not, do so now to pass queued data to user. | ||||
*/ | */ | ||||
if (tlen == 0 && (thflags & TH_FIN) == 0) | if (tlen == 0 && (thflags & TH_FIN) == 0) | ||||
(void) tcp_reass(tp, (struct tcphdr *)0, 0, | (void) tcp_reass(tp, (struct tcphdr *)0, NULL, 0, | ||||
(struct mbuf *)0); | (struct mbuf *)0); | ||||
tp->snd_wl1 = th->th_seq - 1; | tp->snd_wl1 = th->th_seq - 1; | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
/* | /* | ||||
* In ESTABLISHED state: drop duplicate ACKs; ACK out of range | * In ESTABLISHED state: drop duplicate ACKs; ACK out of range | ||||
* ACKs. If the ack is in the range | * ACKs. If the ack is in the range | ||||
* tp->snd_una < th->th_ack <= tp->snd_max | * tp->snd_una < th->th_ack <= tp->snd_max | ||||
▲ Show 20 Lines • Show All 554 Lines • ▼ Show 20 Lines | if ((tlen || (thflags & TH_FIN) || tfo_syn) && | ||||
* connection, and the queue is empty), avoiding linkage into | * connection, and the queue is empty), avoiding linkage into | ||||
* and removal from the queue and repetition of various | * and removal from the queue and repetition of various | ||||
* conversions. | * conversions. | ||||
* Set DELACK for segments received in order, but ack | * Set DELACK for segments received in order, but ack | ||||
* immediately when segments are out of order (so | * immediately when segments are out of order (so | ||||
* fast retransmit can work). | * fast retransmit can work). | ||||
*/ | */ | ||||
if (th->th_seq == tp->rcv_nxt && | if (th->th_seq == tp->rcv_nxt && | ||||
LIST_EMPTY(&tp->t_segq) && | SEGQ_EMPTY(tp) && | ||||
(TCPS_HAVEESTABLISHED(tp->t_state) || | (TCPS_HAVEESTABLISHED(tp->t_state) || | ||||
tfo_syn)) { | tfo_syn)) { | ||||
if (DELAY_ACK(tp, tlen) || tfo_syn) | if (DELAY_ACK(tp, tlen) || tfo_syn) | ||||
tp->t_flags |= TF_DELACK; | tp->t_flags |= TF_DELACK; | ||||
else | else | ||||
tp->t_flags |= TF_ACKNOW; | tp->t_flags |= TF_ACKNOW; | ||||
tp->rcv_nxt += tlen; | tp->rcv_nxt += tlen; | ||||
thflags = th->th_flags & TH_FIN; | thflags = th->th_flags & TH_FIN; | ||||
TCPSTAT_INC(tcps_rcvpack); | TCPSTAT_INC(tcps_rcvpack); | ||||
TCPSTAT_ADD(tcps_rcvbyte, tlen); | TCPSTAT_ADD(tcps_rcvbyte, tlen); | ||||
SOCKBUF_LOCK(&so->so_rcv); | SOCKBUF_LOCK(&so->so_rcv); | ||||
if (so->so_rcv.sb_state & SBS_CANTRCVMORE) | if (so->so_rcv.sb_state & SBS_CANTRCVMORE) | ||||
m_freem(m); | m_freem(m); | ||||
else | else | ||||
sbappendstream_locked(&so->so_rcv, m, 0); | sbappendstream_locked(&so->so_rcv, m, 0); | ||||
/* NB: sorwakeup_locked() does an implicit unlock. */ | /* NB: sorwakeup_locked() does an implicit unlock. */ | ||||
sorwakeup_locked(so); | sorwakeup_locked(so); | ||||
} else { | } else { | ||||
/* | /* | ||||
* XXX: Due to the header drop above "th" is | * XXX: Due to the header drop above "th" is | ||||
* theoretically invalid by now. Fortunately | * theoretically invalid by now. Fortunately | ||||
* m_adj() doesn't actually frees any mbufs | * m_adj() doesn't actually frees any mbufs | ||||
* when trimming from the head. | * when trimming from the head. | ||||
*/ | */ | ||||
thflags = tcp_reass(tp, th, &tlen, m); | thflags = tcp_reass(tp, th, &save_start, &tlen, m); | ||||
tp->t_flags |= TF_ACKNOW; | tp->t_flags |= TF_ACKNOW; | ||||
} | } | ||||
if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT)) | if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT)) | ||||
tcp_update_sack_list(tp, save_start, save_start + tlen); | tcp_update_sack_list(tp, save_start, save_start + tlen); | ||||
#if 0 | #if 0 | ||||
/* | /* | ||||
* Note the amount of data that peer has sent into | * Note the amount of data that peer has sent into | ||||
* our window, in order to estimate the sender's | * our window, in order to estimate the sender's | ||||
▲ Show 20 Lines • Show All 793 Lines • Show Last 20 Lines |