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

📄 tcp_input.c

📁 VxWorks BSP框架源代码包含头文件和驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
					(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) {					tp->snd_cwnd += tp->t_maxseg;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */            WV_NET_PORTOUT_EVENT_2 (NET_CORE_EVENT, WV_NET_WARNING, 13, 6,                              tp->t_inpcb->inp_lport, tp->t_inpcb->inp_fport,                                   WV_NETEVENT_TCPIN_SENDFAIL, WV_NET_RECV,                                    so->so_fd, tp->t_dupacks)#endif  /* INCLUDE_WVNET */#endif					(void) tcp_output(tp);					goto drop;				}			} else				tp->t_dupacks = 0;			break;		}		/*		 * If the congestion window was inflated to account		 * for the other side's cached packets, retract it.		 */		if (tp->t_dupacks > tcprexmtthresh &&		    tp->snd_cwnd > tp->snd_ssthresh)			tp->snd_cwnd = tp->snd_ssthresh;		tp->t_dupacks = 0;		if (SEQ_GT(ti->ti_ack, tp->snd_max)) {			tcpstat.tcps_rcvacktoomuch++;			goto dropafterack;		}		acked = ti->ti_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(ti->ti_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 (ti->ti_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 * (maxseg / 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;		tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);		}		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 ((so->so_snd.sb_want > 0) || (so->so_snd.sb_sel) ||		    (sowakeupHook != NULL))		    {		    if (sbspace (&so->so_snd) >= so->so_snd.sb_lowat)			sowwakeup(so);                    }		tp->snd_una = ti->ti_ack;		if (SEQ_LT(tp->snd_nxt, tp->snd_una))			tp->snd_nxt = tp->snd_una;		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;				}#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_INFO event */            WV_NET_PORTIN_EVENT_1 (NET_AUX_EVENT, WV_NET_INFO, 33, 15,                                   ti->ti_sport, ti->ti_dport,                                   WV_NETEVENT_TCPIN_SENDCLOSED, WV_NET_RECV,                                    so->so_fd)#endif  /* INCLUDE_WVNET */#endif				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) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_INFO event */            WV_NET_PORTIN_EVENT_1 (NET_AUX_EVENT, WV_NET_INFO, 34, 16,                                   ti->ti_sport, ti->ti_dport,                                   WV_NETEVENT_TCPIN_CLOSEWAIT, WV_NET_RECV,                                    so->so_fd)#endif  /* INCLUDE_WVNET */#endif				tp->t_state = TCPS_TIME_WAIT;				tcp_canceltimers(tp);				tp->t_timer[TCPT_2MSL] = 2 * tcp_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:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_INFO event */        WV_NET_PORTIN_EVENT_2 (NET_AUX_EVENT, WV_NET_INFO, 37, 19,                               ti->ti_sport, ti->ti_dport,                               WV_NETEVENT_TCPIN_CLOSE_RESTART, WV_NET_RECV,                               so->so_fd, TRUE)#endif  /* INCLUDE_WVNET */#endif			tp->t_timer[TCPT_2MSL] = 2 * tcp_msl;			goto dropafterack;		}	}step6:	/*	 * Update window information.	 * Don't look at window if no ACK: TAC's send garbage on first SYN.         *         * More specifically, update the window when:         *  1) The ACK flag is set, and either:         *      a) The segment contains new data (snd_wl1 < ti_seq) OR         *      b) The segment is a repeat (snd_wl1 == ti_seq).         *         *  2) In case 1b), one of the following conditions also applies:         *      a) The segment acknowledges more data (snd_wl2 < ti_ack) OR         *      b) No new data is acknowledged, but the window size increases.         *         * The wl2 == ti_ack test might be redundant since the received         * ACK value can't realistically decrease when snd_wl1 == ti_seq.	 */	if ( (tiflags & TH_ACK) &&	    (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||               (tp->snd_wl1 == ti->ti_seq &&	          (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||                  (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))               )            ))            {		/* keep track of pure window updates */		if (ti->ti_len == 0 &&		    tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)			tcpstat.tcps_rcvwinupd++;		tp->snd_wnd = tiwin;		tp->snd_wl1 = ti->ti_seq;		tp->snd_wl2 = ti->ti_ack;		if (tp->snd_wnd > tp->max_sndwnd)			tp->max_sndwnd = tp->snd_wnd;		needoutput = 1;	}	/*	 * Process segments with URG.	 */	if ((tiflags & TH_URG) && ti->ti_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 (ti->ti_urp + so->so_rcv.sb_cc > sb_max) {			ti->ti_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(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {			tp->rcv_up = ti->ti_seq + ti->ti_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 (ti->ti_urp <= ti->ti_len &&		     (so->so_options & SO_OOBINLINE) == 0)			tcp_pulloutofband(so, ti, m);	} else		/*		 * If no out of band data is expected,		 * pull receive urgent pointer along		 * with the receive window.		 */		if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))			tp->rcv_up = tp->rcv_nxt;dodata:							/* XXX */	/*	 * Process the segment text, merging it into the TCP sequencing queue,	 * and arranging for acknowledgment of receipt if necessary.	 * This process logically involves adjusting tp->rcv_wnd as data	 * is presented to the user (this happens in tcp_usrreq.c,	 * case PRU_RCVD).  If a FIN has already been received on this	 * connection then we just ignore the text.	 */	if ((ti->ti_len || (tiflags&TH_FIN)) &&	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {		TCP_REASS(tp, ti, m, so, tiflags);	} else {		m_freem(m);		tiflags &= ~TH_FIN;	}	/*	 * If FIN is received ACK the FIN and let the user know	 * that the connection is closing.	 */	if (tiflags & TH_FIN) {		if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {			socantrcvmore(so);			tp->t_flags |= TF_ACKNOW;			tp->rcv_nxt++;		}		switch (tp->t_state) {	 	/*		 * In ESTABLISHED state		 * enter the CLOSE_WAIT state.		 */		case TCPS_SYN_RECEIVED:                    break;          /* avoid SYN+FIN death */		case TCPS_ESTABLISHED:		#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_INFO event */        WV_NET_PORTIN_EVENT_1 (NET_AUX_EVENT, WV_NET_INFO, 35, 17,                               ti->ti_sport, ti->ti_dport,                               WV_NETEVENT_TCPIN_RECVCLOSED, WV_NET_RECV,                               so->so_fd)#endif  /* INCLUDE_WVNET */#endif			tp->t_state = TCPS_CLOSE_WAIT;			break;	 	/*		 * If still in FIN_WAIT_1 STATE FIN has not been acked so		 * enter the CLOSING state.		 */		case TCPS_FIN_WAIT_1:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_INFO event */            WV_NET_PORTIN_EVENT_1 (NET_AUX_EVENT, WV_NET_INFO, 36, 18,                                   ti->ti_sport, ti->ti_dport,                                   WV_NETEVENT_TCPIN_CLOSING, WV_NET_RECV,                                   so->so_fd)#endif  /* INCLUDE_WVNET */#endif			tp->t_state = TCPS_CLOSING;			break;	 	/*		 * In FIN_WAIT_2 state enter the TIME_WAIT state,		 * starting the time-wait timer, turning off the other 		 * standard timers.		 */		case TCPS_FIN_WAIT_2:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_INFO event */            WV_NET_PORTIN_EVENT_1 (NET_AUX_EVENT, WV_NET_INFO, 34, 16,                                   ti->ti_sport, ti->ti_dport,                                   WV_NETEVENT_TCPIN_CLOSEWAIT, WV_NET_RECV,                                   so->so_fd)#endif  /* INCLUDE_WVNET */#endif			tp->t_state = TCPS_TIME_WAIT;			tcp_canceltimers(tp);			tp->t_timer[TCPT_2MSL] = 2 * tcp_msl;			soisdisconnected(so);			break;		/*		 * In TIME_WAIT state restart the 2 MSL time_wait timer.		 */		case TCPS_TIME_WAIT:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET    /* WV_NET_INFO event */        WV_NET_PORTIN_EVENT_2 (NET_AUX_EVENT, WV_NET_INFO, 37, 19,                               ti->ti_sport, ti->ti_dport,                               WV_NETEVENT_TCPIN_CLOSE_RESTART, WV_NET_RECV,                               so->so_fd, FALSE)#endif  /* INCLUDE_WVNET */#endif			tp->t_timer[TCPT_2MSL] = 2 * tcp_msl;			break;		}	}	if (so->so_options & SO_DEBUG)		(*tcpTraceRtn)(TA_INPUT, ostate, tp, &tcp_saveti, 0);	/*	 * Return any desired output.	 */	if (needoutput || (tp->t_flags & TF_ACKNOW))		(void) tcp_output(tp);	return;dropafterack:	/*	 * Generate an ACK dropping incoming segment if it occupies	 * sequence space, where the ACK reflects our state.	 */	if (tiflags & TH_RST)		goto drop;	m_freem(m);	tp->t_flags |= TF_ACKNOW;	(void) tcp_output(tp);	return;dropwithreset:	/*	 * Generate a RST, dropping incoming segment.	 * Make ACK acceptable to originator of segment.	 * Don't bother to respond if destination was broadcast/multicast.

⌨️ 快捷键说明

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