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

📄 tcp-full.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
📖 第 1 页 / 共 5 页
字号:
			} else {				flags_ |= TF_ACKNOW;	// ACK peer's SYN			}                        /*                         * Received <SYN,ACK> in SYN_SENT[*] state.                         * Transitions:                         *      SYN_SENT  --> ESTABLISHED                         *      SYN_SENT* --> FIN_WAIT_1                         */			if (flags_ & TF_NEEDFIN) {				newstate(TCPS_FIN_WAIT_1);				flags_ &= ~TF_NEEDFIN;				tiflags &= ~TH_SYN;			} else {				newstate(TCPS_ESTABLISHED);			}			// special to ns:			//  generate pure ACK here.			//  this simulates the ordinary connection establishment			//  where the ACK of the peer's SYN+ACK contains			//  no data.  This is typically caused by the way			//  the connect() socket call works in which the			//  entire 3-way handshake occurs prior to the app			//  being able to issue a write() [which actually			//  causes the segment to be sent].			sendpacket(t_seqno_, rcv_nxt_, TH_ACK, 0, 0);		} else {			// Check ECN-SYN packet                        if (ecn_ && fh->ecnecho() && fh->cong_action())                                ect_ = TRUE;			// SYN (no ACK) (simultaneous active opens)			flags_ |= TF_ACKNOW;			cancel_rtx_timer();			newstate(TCPS_SYN_RECEIVED);			/*			 * decrement t_seqno_: we are sending a			 * 2nd SYN (this time in the form of a			 * SYN+ACK, so t_seqno_ will have been			 * advanced to 2... reduce this			 */			t_seqno_--;	// CHECKME		}trimthenstep6:		/*		 * advance the seq# to correspond to first data byte		 */		tcph->seqno()++;		if (tiflags & TH_ACK)			goto process_ACK;		goto step6;	case TCPS_LAST_ACK:		/* 		 * The only way we're in LAST_ACK is if we've already		 * received a FIN, so ignore all retranmitted FINS.		 * -M. Weigle 7/23/02		 */		if (tiflags & TH_FIN) {			goto drop;		}		break;	case TCPS_CLOSING:		break;	} /* end switch(state_) */        /*         * States other than LISTEN or SYN_SENT.         * First check timestamp, if present.         * Then check that at least some bytes of segment are within         * receive window.  If segment begins before rcv_nxt,         * drop leading data (and SYN); if nothing left, just ack.         *         * RFC 1323 PAWS: If we have a timestamp reply on this segment         * and it's less than ts_recent, drop it.         */	if (ts_option_ && !fh->no_ts_ && recent_ && tcph->ts() < recent_) {		if ((now() - recent_age_) > TCP_PAWS_IDLE) {			/*			 * this is basically impossible in the simulator,			 * but here it is...			 */                        /*                         * Invalidate ts_recent.  If this segment updates                         * ts_recent, the age will be reset later and ts_recent                         * will get a valid value.  If it does not, setting                         * ts_recent to zero will at least satisfy the                         * requirement that zero be placed in the timestamp                         * echo reply when ts_recent isn't valid.  The                         * age isn't reset until we get a valid ts_recent                         * because we don't want out-of-order segments to be                         * dropped when ts_recent is old.                         */			recent_ = 0.0;		} else {			fprintf(stderr, "%f: FullTcpAgent(%s): dropped pkt due to bad ts\n",				now(), name());			goto dropafterack;		}	}	// check for redundant data at head/tail of segment	//	note that the 4.4bsd [Net/3] code has	//	a bug here which can cause us to ignore the	//	perfectly good ACKs on duplicate segments.  The	//	fix is described in (Stevens, Vol2, p. 959-960).	//	This code is based on that correction.	//	// In addition, it has a modification so that duplicate segments	// with dup acks don't trigger a fast retransmit when dupseg_fix_	// is enabled.	//	// Yet one more modification: make sure that if the received	//	segment had datalen=0 and wasn't a SYN or FIN that	//	we don't turn on the ACKNOW status bit.  If we were to	//	allow ACKNOW to be turned on, normal pure ACKs that happen	//	to have seq #s below rcv_nxt can trigger an ACK war by	//	forcing us to ACK the pure ACKs	//	// Update: if we have a dataless FIN, don't really want to	// do anything with it.  In particular, would like to	// avoid ACKing an incoming FIN+ACK while in CLOSING	//	todrop = rcv_nxt_ - tcph->seqno();  // how much overlap?	if (todrop > 0 && ((tiflags & (TH_SYN)) || datalen > 0)) {//printf("%f(%s): trim 1..todrop:%d, dlen:%d\n",now(), name(), todrop, datalen);		if (tiflags & TH_SYN) {			tiflags &= ~TH_SYN;			tcph->seqno()++;			th->size()--;	// XXX Must decrease packet size too!!					// Q: Why?.. this is only a SYN			todrop--;		}		//		// see Stevens, vol 2, p. 960 for this check;		// this check is to see if we are dropping		// more than this segment (i.e. the whole pkt + a FIN),		// or just the whole packet (no FIN)		//		if ((todrop > datalen) ||		    (todrop == datalen && ((tiflags & TH_FIN) == 0))) {//printf("%f(%s): trim 2..todrop:%d, dlen:%d\n",now(), name(), todrop, datalen);                        /*                         * Any valid FIN must be to the left of the window.                         * At this point the FIN must be a duplicate or out                         * of sequence; drop it.                         */			tiflags &= ~TH_FIN;			/*			 * Send an ACK to resynchronize and drop any data.			 * But keep on processing for RST or ACK.			 */			flags_ |= TF_ACKNOW;			todrop = datalen;			dupseg = TRUE;	// *completely* duplicate		}		/*		 * Trim duplicate data from the front of the packet		 */		tcph->seqno() += todrop;		th->size() -= todrop;	// XXX Must decrease size too!!					// why? [kf]..prob when put in RQ		datalen -= todrop;	} /* data trim */	/*	 * If we are doing timstamps and this packet has one, and	 * If last ACK falls within this segment's sequence numbers,	 * record the timestamp.	 * See RFC1323 (now RFC1323 bis)	 */	if (ts_option_ && !fh->no_ts_ && tcph->seqno() <= last_ack_sent_) {		/*		 * this is the case where the ts value is newer than		 * the last one we've seen, and the seq # is the one we expect		 * [seqno == last_ack_sent_] or older		 */		recent_age_ = now();		recent_ = tcph->ts();	}	if (tiflags & TH_SYN) {		fprintf(stderr,		    "%f: FullTcpAgent::recv(%s) received unexpected SYN (state:%d): ",		        now(), name(), state_);		prpkt(pkt);		goto dropwithreset;	}	if ((tiflags & TH_ACK) == 0) {		/*		 * Added check for state != SYN_RECEIVED.  We will receive a 		 * duplicate SYN in SYN_RECEIVED when our SYN/ACK was dropped.		 * We should just ignore the duplicate SYN (our timeout for 		 * resending the SYN/ACK is about the same as the client's 		 * timeout for resending the SYN), but give no error message. 		 * -M. Weigle 07/24/01		 */		if (state_ != TCPS_SYN_RECEIVED) {			fprintf(stderr, "%f: FullTcpAgent::recv(%s) got packet lacking ACK (state:%d): ",				now(), name(), state_);			prpkt(pkt);			goto drop;		}	}	/*	 * Ack processing.	 */	switch (state_) {	case TCPS_SYN_RECEIVED:	/* want ACK for our SYN+ACK */		if (ackno < highest_ack_ || ackno > maxseq_) {			// not in useful range		    	fprintf(stderr,		    		"%f: FullTcpAgent(%s): ack(%d) not in range while in SYN_RECEIVED: ",			 	now(), name(), ackno);			prpkt(pkt);			goto dropwithreset;		}                /*                 * Make transitions:                 *      SYN-RECEIVED  -> ESTABLISHED                 *      SYN-RECEIVED* -> FIN-WAIT-1                 */                if (flags_ & TF_NEEDFIN) {			newstate(TCPS_FIN_WAIT_1);                        flags_ &= ~TF_NEEDFIN;                } else {                        newstate(TCPS_ESTABLISHED);                }		cwnd_ = initial_window();		/* 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.	 *	 * note that state TIME_WAIT isn't used	 * in the simulator         */        case TCPS_ESTABLISHED:        case TCPS_FIN_WAIT_1:        case TCPS_FIN_WAIT_2:	case TCPS_CLOSE_WAIT:        case TCPS_CLOSING:        case TCPS_LAST_ACK:		//		// look for ECNs in ACKs, react as necessary		//		if (fh->ecnecho() && (!ecn_ || !ect_)) {			fprintf(stderr,			    "%f: FullTcp(%s): warning, recvd ecnecho but I am not ECN capable!\n",				now(), name());		}                //                // generate a stream of ecnecho bits until we see a true                // cong_action bit                //                 if (ecn_) {                        if (fh->ce() && fh->ect())                                recent_ce_ = TRUE;                        else if (fh->cwr())                                recent_ce_ = FALSE;                }		//		// If ESTABLISHED or starting to close, process SACKS		//		if (state_ >= TCPS_ESTABLISHED && tcph->sa_length() > 0) {			process_sack(tcph);		}		//		// ACK indicates packet left the network		//	try not to be fooled by data		//		if (fastrecov_ && (datalen == 0 || ackno > highest_ack_))			pipe_ -= maxseg_;		// look for dup ACKs (dup ack numbers, no data)		//		// do fast retransmit/recovery if at/past thresh		if (ackno <= highest_ack_) {			// a pure ACK which doesn't advance highest_ack_			if (datalen == 0 && (!dupseg_fix_ || !dupseg)) {                                /*                                 * If we have outstanding data                                 * this is a completely                                 * duplicate ack,                                 * 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.                                 *                                 * We know we're losing at the current                                 * window size so do congestion avoidance.                                 *                                 * 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 ((rtx_timer_.status() != TIMER_PENDING) ||				    ackno < highest_ack_) {					// Q: significance of timer not pending?					// ACK below highest_ack_					oldack();				} else if (++dupacks_ == tcprexmtthresh_) {					// ACK at highest_ack_ AND meets threshold					//trace_event("FAST_RECOVERY");					dupack_action(); // maybe fast rexmt					goto drop;				} else if (dupacks_ > tcprexmtthresh_) {					// ACK at highest_ack_ AND above threshole					//trace_event("FAST_RECOVERY");					extra_ack();					// send whatever window allows					send_much(0, REASON_DUPACK, maxburst_);					goto drop;				}			} else {				// non zero-length [dataful] segment				// with a dup ack (normal for dataful segs)				// (or window changed in real TCP).				if (dupack_reset_) {					dupacks_ = 0;					fastrecov_ = FALSE;				}			}			break;	/* take us to "step6" */		} /* end of dup/old acks */		/*		 * we've finished the fast retransmit/recovery period		 * (i.e. received an ACK which advances highest_ack_)		 * The ACK may be "good" or "partial"		 */process_ACK:		if (ackno > maxseq_) {			// ack more than we sent(!?)			fprintf(stderr,			    "%f: FullTcpAgent::recv(%s) too-big ACK (maxseq:%d): ",				now(), name(), int(maxseq_));			prpkt(pkt);			goto dropafterack;		}                /*                 * 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 all outstanding data is acked, stop retransmit                 * If there is more data to be acked, restart retransmit                 * timer, using current (possibly backed-off) value.                 */		newack(pkt);	// handle timers, update highest_ack_		/*		 * if this is a partial ACK, invoke whatever we should		 * note that newack() must be called before the action		 * functions, as some of them depend on side-effects		 * of newack()		 */		int partial = pack(pkt);		if (partial)			pack_action(pkt);		else			ack_action(pkt);		/*		 * if this is an ACK with an ECN indication, handle this		 * but not if it is a syn packet		 */		if (fh->ecnecho() && !(tiflags&TH_SYN) )		if (fh->ecnecho()) {			// Note from Sally: In one-way TCP,			// ecn() is called before newack()...			ecn(highest_ack_);  // updated by newack(), above			// "set_rtx_timer();" from T. Kelly.			if (cwnd_ < 1)			 	set_rtx_timer();		}		// CHECKME: handling of rtx timer		if (ackno == maxseq_) {			needoutput = TRUE;		}		/*		 * If no data (only SYN) was ACK'd,		 *    skip rest of ACK processing.		 */		if (ackno == (highest_ack_ + 1))			goto step6;		// if we are delaying initial cwnd growth (probably due to		// large initial windows), then only open cwnd if data has		// been received		// Q: check whe

⌨️ 快捷键说明

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