⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp_input.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 5 页
字号:
			goto drop;		}	}	/*	 * If a SYN is in the window, then this is an	 * error and we send an RST and drop the connection.	 */	if (tiflags & TH_SYN) {		tp = tcp_drop(tp, ECONNRESET);		goto dropwithreset;	}	/*	 * If the ACK bit is off we drop the segment and return.	 */	if ((tiflags & TH_ACK) == 0) {		if (tp->t_flags & TF_ACKNOW)			goto dropafterack;		else			goto drop;	}		/*	 * Ack processing.	 */	switch (tp->t_state) {	/*	 * In SYN_RECEIVED state, the ack ACKs our SYN, so enter	 * ESTABLISHED state and continue processing.	 * The ACK was checked above.	 */	case TCPS_SYN_RECEIVED:		tcpstat.tcps_connects++;		soisconnected(so);		tp->t_state = TCPS_ESTABLISHED;		/* Do window scaling? */		if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==			(TF_RCVD_SCALE|TF_REQ_SCALE)) {			tp->snd_scale = tp->requested_s_scale;			tp->rcv_scale = tp->request_r_scale;		}		(void) tcp_reass(tp, (struct tcphdr *)0, (struct mbuf *)0,				 &tlen);		tp->snd_wl1 = th->th_seq - 1;		/* fall into ... */	/*	 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range	 * ACKs.  If the ack is in the range	 *	tp->snd_una < ti->ti_ack <= tp->snd_max	 * then advance tp->snd_una to ti->ti_ack and drop	 * data from the retransmission queue.  If this ACK reflects	 * more up to date window information we update our window information.	 */	case TCPS_ESTABLISHED:	case TCPS_FIN_WAIT_1:	case TCPS_FIN_WAIT_2:	case TCPS_CLOSE_WAIT:	case TCPS_CLOSING:	case TCPS_LAST_ACK:	case TCPS_TIME_WAIT:		if (SEQ_LEQ(th->th_ack, tp->snd_una)) {			/*			 * Duplicate/old ACK processing.			 * Increments t_dupacks:			 *	Pure duplicate (same seq/ack/window, no data)			 * Doesn't affect t_dupacks:			 *	Data packets.			 *	Normal window updates (window opens)			 * Resets t_dupacks:			 *	New data ACKed.			 *	Window shrinks			 *	Old ACK			 */			if (tlen)				break;			/*			 * If we get an old ACK, there is probably packet			 * reordering going on.  Be conservative and reset			 * t_dupacks so that we are less agressive in			 * doing a fast retransmit.			 */			if (th->th_ack != tp->snd_una) {				tp->t_dupacks = 0;				break;			}			if (tiwin == tp->snd_wnd) {				tcpstat.tcps_rcvdupack++;				/*				 * If we have outstanding data (other than				 * a window probe), this is a completely				 * duplicate ack (ie, window info didn't				 * change), the ack is the biggest we've				 * seen and we've seen exactly our rexmt				 * threshhold of them, assume a packet				 * has been dropped and retransmit it.				 * Kludge snd_nxt & the congestion				 * window so we send only this one				 * packet.				 *				 * We know we're losing at the current				 * window size so do congestion avoidance				 * (set ssthresh to half the current window				 * and pull our congestion window back to				 * the new ssthresh).				 *				 * Dup acks mean that packets have left the				 * network (they're now cached at the receiver) 				 * so bump cwnd by the amount in the receiver				 * to keep a constant cwnd packets in the				 * network.				 */				if (tp->t_timer[TCPT_REXMT] == 0)					tp->t_dupacks = 0;#if defined(TCP_SACK) && defined(TCP_FACK)				/* 				 * In FACK, can enter fast rec. if the receiver				 * reports a reass. queue longer than 3 segs.				 */				else if (++tp->t_dupacks == tcprexmtthresh ||				    ((SEQ_GT(tp->snd_fack, tcprexmtthresh * 				    tp->t_maxseg + tp->snd_una)) &&				    SEQ_GT(tp->snd_una, tp->snd_last))) {#else				else if (++tp->t_dupacks == tcprexmtthresh) {#endif /* TCP_FACK */					tcp_seq onxt = tp->snd_nxt;					u_long win =					    ulmin(tp->snd_wnd, tp->snd_cwnd) /						2 / tp->t_maxseg;#if defined(TCP_SACK) 					if (SEQ_LT(th->th_ack, tp->snd_last)){					    	/* 						 * False fast retx after 						 * timeout.  Do not cut window.						 */						tp->snd_cwnd += tp->t_maxseg;						tp->t_dupacks = 0;						(void) tcp_output(tp); 						goto drop;					}#endif					if (win < 2)						win = 2;					tp->snd_ssthresh = win * tp->t_maxseg;#if defined(TCP_SACK)					tp->snd_last = tp->snd_max;#endif#ifdef TCP_SACK                    			if (!tp->sack_disable) {						tp->t_timer[TCPT_REXMT] = 0;						tp->t_rtt = 0;						tcpstat.tcps_sndrexmitfast++;#if defined(TCP_SACK) && defined(TCP_FACK) 						(void) tcp_output(tp);						/*						 * During FR, snd_cwnd is held						 * constant for FACK.						 */						tp->snd_cwnd = tp->snd_ssthresh;						tp->t_dupacks = tcprexmtthresh;#else						/* 						 * tcp_output() will send						 * oldest SACK-eligible rtx.						 */						(void) tcp_output(tp);						tp->snd_cwnd = tp->snd_ssthresh+					           tp->t_maxseg * tp->t_dupacks;#endif /* TCP_FACK */						goto drop;					}#endif /* TCP_SACK */					tp->t_timer[TCPT_REXMT] = 0;					tp->t_rtt = 0;					tp->snd_nxt = th->th_ack;					tp->snd_cwnd = tp->t_maxseg;					tcpstat.tcps_sndrexmitfast++;					(void) tcp_output(tp);					tp->snd_cwnd = tp->snd_ssthresh +					    tp->t_maxseg * tp->t_dupacks;					if (SEQ_GT(onxt, tp->snd_nxt))						tp->snd_nxt = onxt;					goto drop;				} else if (tp->t_dupacks > tcprexmtthresh) {#if defined(TCP_SACK) && defined(TCP_FACK)					/* 					 * while (awnd < cwnd) 					 *         sendsomething(); 					 */					if (!tp->sack_disable) {						if (tp->snd_awnd < tp->snd_cwnd)							tcp_output(tp);						goto drop;					}#endif /* TCP_FACK */					tp->snd_cwnd += tp->t_maxseg;					(void) tcp_output(tp);					goto drop;				}			} else if (tiwin < tp->snd_wnd) {				/*				 * The window was retracted!  Previous dup				 * ACKs may have been due to packets arriving				 * after the shrunken window, not a missing				 * packet, so play it safe and reset t_dupacks				 */				tp->t_dupacks = 0;			}			break;		}		/*		 * If the congestion window was inflated to account		 * for the other side's cached packets, retract it.		 */#if defined(TCP_SACK)		if (!tp->sack_disable) {			if (tp->t_dupacks >= tcprexmtthresh) {				/* Check for a partial ACK */				if (tcp_sack_partialack(tp, th)) {#if defined(TCP_SACK) && defined(TCP_FACK)					/* Force call to tcp_output */					if (tp->snd_awnd < tp->snd_cwnd) 						needoutput = 1;#else					tp->snd_cwnd += tp->t_maxseg;					needoutput = 1;#endif /* TCP_FACK */				} else {					/* Out of fast recovery */					tp->snd_cwnd = tp->snd_ssthresh;					if (tcp_seq_subtract(tp->snd_max, 					    th->th_ack) < tp->snd_ssthresh)						tp->snd_cwnd = 						   tcp_seq_subtract(tp->snd_max,					           th->th_ack) + tp->t_maxseg;					tp->t_dupacks = 0;#if defined(TCP_SACK) && defined(TCP_FACK)					if (SEQ_GT(th->th_ack, tp->snd_fack))						tp->snd_fack = th->th_ack;#endif /* TCP_FACK */				}			} 		} else {			if (tp->t_dupacks >= tcprexmtthresh && 			    !tcp_newreno(tp, th)) {				/* Out of fast recovery */				tp->snd_cwnd = tp->snd_ssthresh;				if (tcp_seq_subtract(tp->snd_max, th->th_ack) <			  	    tp->snd_ssthresh)					tp->snd_cwnd = 					    tcp_seq_subtract(tp->snd_max,					    th->th_ack) + tp->t_maxseg;				tp->t_dupacks = 0;			}		}		if (tp->t_dupacks < tcprexmtthresh)			tp->t_dupacks = 0;#else /* else no TCP_SACK */		if (tp->t_dupacks >= tcprexmtthresh &&		    tp->snd_cwnd > tp->snd_ssthresh)			tp->snd_cwnd = tp->snd_ssthresh;		tp->t_dupacks = 0;#endif		if (SEQ_GT(th->th_ack, tp->snd_max)) {			tcpstat.tcps_rcvacktoomuch++;			goto dropafterack;		}		acked = th->th_ack - tp->snd_una;		tcpstat.tcps_rcvackpack++;		tcpstat.tcps_rcvackbyte += acked;		/*		 * If we have a timestamp reply, update smoothed		 * round trip time.  If no timestamp is present but		 * transmit timer is running and timed sequence		 * number was acked, update smoothed round trip time.		 * Since we now have an rtt measurement, cancel the		 * timer backoff (cf., Phil Karn's retransmit alg.).		 * Recompute the initial retransmit timer.		 */		if (ts_present)			tcp_xmit_timer(tp, tcp_now-ts_ecr+1);		else if (tp->t_rtt && SEQ_GT(th->th_ack, tp->t_rtseq))			tcp_xmit_timer(tp,tp->t_rtt);		/*		 * If all outstanding data is acked, stop retransmit		 * timer and remember to restart (more output or persist).		 * If there is more data to be acked, restart retransmit		 * timer, using current (possibly backed-off) value.		 */		if (th->th_ack == tp->snd_max) {			tp->t_timer[TCPT_REXMT] = 0;			needoutput = 1;		} else if (tp->t_timer[TCPT_PERSIST] == 0)			tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;		/*		 * When new data is acked, open the congestion window.		 * If the window gives us less than ssthresh packets		 * in flight, open exponentially (maxseg per packet).		 * Otherwise open linearly: maxseg per window		 * (maxseg^2 / cwnd per packet).		 */		{		register u_int cw = tp->snd_cwnd;		register u_int incr = tp->t_maxseg;		if (cw > tp->snd_ssthresh)			incr = incr * incr / cw;#if defined (TCP_SACK)		if (SEQ_GEQ(th->th_ack, tp->snd_last)) #endif		tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);		}		ND6_HINT(tp);		if (acked > so->so_snd.sb_cc) {			tp->snd_wnd -= so->so_snd.sb_cc;			sbdrop(&so->so_snd, (int)so->so_snd.sb_cc);			ourfinisacked = 1;		} else {			sbdrop(&so->so_snd, acked);			tp->snd_wnd -= acked;			ourfinisacked = 0;		}		if (sb_notify(&so->so_snd))			sowwakeup(so);		tp->snd_una = th->th_ack;		if (SEQ_LT(tp->snd_nxt, tp->snd_una))			tp->snd_nxt = tp->snd_una;#if defined (TCP_SACK) && defined (TCP_FACK)		if (SEQ_GT(tp->snd_una, tp->snd_fack))			tp->snd_fack = tp->snd_una;#endif		switch (tp->t_state) {		/*		 * In FIN_WAIT_1 STATE in addition to the processing		 * for the ESTABLISHED state if our FIN is now acknowledged		 * then enter FIN_WAIT_2.		 */		case TCPS_FIN_WAIT_1:			if (ourfinisacked) {				/*				 * If we can't receive any more				 * data, then closing user can proceed.				 * Starting the timer is contrary to the				 * specification, but if we don't get a FIN				 * we'll hang forever.				 */				if (so->so_state & SS_CANTRCVMORE) {					soisdisconnected(so);					tp->t_timer[TCPT_2MSL] = tcp_maxidle;				}				tp->t_state = TCPS_FIN_WAIT_2;			}			break;		/*		 * In CLOSING STATE in addition to the processing for		 * the ESTABLISHED state if the ACK acknowledges our FIN		 * then enter the TIME-WAIT state, otherwise ignore		 * the segment.		 */		case TCPS_CLOSING:			if (ourfinisacked) {				tp->t_state = TCPS_TIME_WAIT;				tcp_canceltimers(tp);				tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;				soisdisconnected(so);			}			break;		/*		 * In LAST_ACK, we may still be waiting for data to drain		 * and/or to be acked, as well as for the ack of our FIN.		 * If our FIN is now acknowledged, delete the TCB,		 * enter the closed state and return.		 */		case TCPS_LAST_ACK:			if (ourfinisacked) {				tp = tcp_close(tp);				goto drop;			}			break;		/*		 * In TIME_WAIT state the only thing that should arrive		 * is a retransmission of the remote FIN.  Acknowledge		 * it and restart the finack timer.		 */		case TCPS_TIME_WAIT:			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;			goto dropafterack;		}	}step6:	/*	 * Update window information.	 * Don't look at window if no ACK: TAC's send garbage on first SYN.	 */	if ((tiflags & TH_ACK) && (SEQ_LT(tp->snd_wl1, th->th_seq) ||	    (tp->snd_wl1 == th->th_seq && SEQ_LT(tp->snd_wl2, th->th_ack)) ||	    (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))) {		/* keep track of pure window updates */		if (tlen == 0 &&		    tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd)			tcpstat.tcps_rcvwinupd++;		tp->snd_wnd = tiwin;		tp->snd_wl1 = th->th_seq;		tp->snd_wl2 = th->th_ack;		if (tp->snd_wnd > tp->max_sndwnd)			tp->max_sndwnd = tp->snd_wnd;		needoutput = 1;	}	/*	 * Process segments with URG.	 */	if ((tiflags & TH_URG) && th->th_urp &&	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {		/*		 * This is a kludge, but if we receive and accept		 * random urgent pointers, we'll crash in		 * soreceive.  It's hard to imagine someone		 * actually wanting to send this much urgent data.		 */		if (th->th_urp + so->so_rcv.sb_cc > sb_max) {			th->th_urp = 0;			/* XXX */			tiflags &= ~TH_URG;		/* XXX */			goto dodata;			/* XXX */		}		/*		 * If this segment advances the known urgent pointer,		 * then mark the data stream.  This should not happen		 * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since		 * a FIN has been received from the remote side. 		 * In these states we ignore the URG.		 *		 * According to RFC961 (Assigned Protocols),		 * the urgent pointer points to the last octet		 * of urgent data.  We continue, however,		 * to consider it to indicate the first octet		 * of data past the urgent section as the original 		 * spec states (in one of two places).		 */		if (SEQ_GT(th->th_seq+th->th_urp, tp->rcv_up)) {			tp->rcv_up = th->th_seq + th->th_urp;			so->so_oobmark = so->so_rcv.sb_cc +			    (tp->rcv_up - tp->rcv_nxt) - 1;			if (so->so_oobmark == 0)				so->so_state |= SS_RCVATMARK;			sohasoutofband(so);			tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);		}		/*		 * Remove out of band data so doesn't get presented to user.		 * This can happen independent of advancing the URG pointer,		 * but if two URG's are pending at once, some out-of-band		 * data may creep in... ick.		 */		if (th->th_urp <= (u_int16_t) tlen#ifdef SO_OOBINLINE		     && (so->so_options & SO_OOBINLINE) == 0#endif		     )		        tcp_pulloutofband(so, th->th_urp, m, hdroptlen);	} else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -