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

📄 tcp.cc

📁 diff serve for ns-2, work for version 2.29
💻 CC
📖 第 1 页 / 共 5 页
字号:
	if (ssthresh_ < 2)		ssthresh_ = 2;	if (how & (CLOSE_CWND_HALF|CLOSE_CWND_RESTART|CLOSE_CWND_INIT|CLOSE_CWND_ONE))		cong_action_ = TRUE;	fcnt_ = count_ = 0;	if (first_decrease_ == 1)		first_decrease_ = 0;	// for event tracing slow start	if (cwnd_ == 1 || slowstart) 		// Not sure if this is best way to capture slow_start		// This is probably tracing a superset of slowdowns of		// which all may not be slow_start's --Padma, 07/'01.		trace_event("SLOW_START");		}/* * Process a packet that acks previously unacknowleged data. */void TcpAgent::newack(Packet* pkt){	double now = Scheduler::instance().clock();	hdr_tcp *tcph = hdr_tcp::access(pkt);	/* 	 * Wouldn't it be better to set the timer *after*	 * updating the RTT, instead of *before*? 	 */	if (!timerfix_) newtimer(pkt);	dupacks_ = 0;	last_ack_ = tcph->seqno();	prev_highest_ack_ = highest_ack_ ;	highest_ack_ = last_ack_;	if (t_seqno_ < last_ack_ + 1)		t_seqno_ = last_ack_ + 1;	/* 	 * Update RTT only if it's OK to do so from info in the flags header.	 * This is needed for protocols in which intermediate agents	 * in the network intersperse acks (e.g., ack-reconstructors) for	 * various reasons (without violating e2e semantics).	 */		hdr_flags *fh = hdr_flags::access(pkt);	if (!fh->no_ts_) {		if (ts_option_) {			ts_echo_=tcph->ts_echo();			rtt_update(now - tcph->ts_echo());			if (ts_resetRTO_ && (!ect_ || !ecn_backoff_ ||			    !hdr_flags::access(pkt)->ecnecho())) { 				// From Andrei Gurtov				/* 				 * Don't end backoff if still in ECN-Echo with			 	 * a congestion window of 1 packet. 				 */				t_backoff_ = 1;				ecn_backoff_ = 0;			}		}		if (rtt_active_ && tcph->seqno() >= rtt_seq_) {			if (!ect_ || !ecn_backoff_ || 				!hdr_flags::access(pkt)->ecnecho()) {				/* 				 * Don't end backoff if still in ECN-Echo with			 	 * a congestion window of 1 packet. 				 */				t_backoff_ = 1;				ecn_backoff_ = 0;			}			rtt_active_ = 0;			if (!ts_option_)				rtt_update(now - rtt_ts_);		}	}	if (timerfix_) newtimer(pkt);	/* update average window */	awnd_ *= 1.0 - wnd_th_;	awnd_ += wnd_th_ * cwnd_;}/* * Respond either to a source quench or to a congestion indication bit. * This is done at most once a roundtrip time;  after a source quench, * another one will not be done until the last packet transmitted before * the previous source quench has been ACKed. * * Note that this procedure is called before "highest_ack_" is * updated to reflect the current ACK packet.   */void TcpAgent::ecn(int seqno){	if (seqno > recover_ || 	      last_cwnd_action_ == CWND_ACTION_TIMEOUT) {		recover_ =  maxseq_;		last_cwnd_action_ = CWND_ACTION_ECN;		if (cwnd_ <= 1.0) {			if (ecn_backoff_) 				rtt_backoff();			else ecn_backoff_ = 1;		} else ecn_backoff_ = 0;		slowdown(CLOSE_CWND_HALF|CLOSE_SSTHRESH_HALF);		++necnresponses_ ;		// added by sylvia to count number of ecn responses 	}}/* *  Is the connection limited by the network (instead of by a lack *    of data from the application? */int TcpAgent::network_limited() {	int win = window () ;	if (t_seqno_ > (prev_highest_ack_ + win))		return 1;	else		return 0;}void TcpAgent::recv_newack_helper(Packet *pkt) {	//hdr_tcp *tcph = hdr_tcp::access(pkt);	newack(pkt);        if (qs_window_ && highest_ack_ >= qs_window_) {                // All segments in the QS window have been acknowledged.                // We can exit the Quick-Start phase.                qs_window_ = 0;        }	if (!ect_ || !hdr_flags::access(pkt)->ecnecho() ||		(old_ecn_ && ecn_burst_)) {		/* If "old_ecn", this is not the first ACK carrying ECN-Echo		 * after a period of ACKs without ECN-Echo.		 * Therefore, open the congestion window. */		/* if control option is set, and the sender is not			 window limited, then do not increase the window size */				if (!control_increase_ || 		   (control_increase_ && (network_limited() == 1))) 	      		opencwnd();	}	if (ect_) {		if (!hdr_flags::access(pkt)->ecnecho())			ecn_backoff_ = 0;		if (!ecn_burst_ && hdr_flags::access(pkt)->ecnecho())			ecn_burst_ = TRUE;		else if (ecn_burst_ && ! hdr_flags::access(pkt)->ecnecho())			ecn_burst_ = FALSE;	}	if (!ect_ && hdr_flags::access(pkt)->ecnecho() &&		!hdr_flags::access(pkt)->cong_action())		ect_ = 1;	/* if the connection is done, call finish() */	if ((highest_ack_ >= curseq_-1) && !closed_) {		closed_ = 1;		finish();	}	if (QOption_ && curseq_ == highest_ack_ +1) {		cancel_rtx_timer();	}	if (frto_ == 1) {		/*		 * New ack after RTO. If F-RTO is enabled, try to transmit new		 * previously unsent segments.		 * If there are no new data or receiver window limits the		 * transmission, revert to traditional recovery.		 */		if (recover_ + 1 >= highest_ack_ + wnd_ ||		    recover_ + 1 >= curseq_) {			frto_ = 0; 		} else if (highest_ack_ == recover_) { 			/* 			 * F-RTO step 2a) RTO retransmission fixes whole			 * window => cancel F-RTO 			 */ 			frto_ = 0;		} else {			t_seqno_ = recover_ + 1;			frto_ = 2;		}	} else if (frto_ == 2) {		/*		 * Second new ack after RTO. If F-RTO is enabled, RTO can be		 * declared spurious		 */		spurious_timeout();	}}/* * Set the initial window.  */doubleTcpAgent::initial_window(){        // If Quick-Start Request was approved, use that as a basis for        // initial window        if (qs_cwnd_) {                return (qs_cwnd_);        }	//	// init_option = 1: static iw of wnd_init_	//	if (wnd_init_option_ == 1) {		return (wnd_init_);	}        else if (wnd_init_option_ == 2) {		// do iw according to Internet draft 		if (size_ <= 1095) {			return (4.0);	 	} else if (size_ < 2190) {			return (3.0);		} else {			return (2.0);		}	}	// XXX what should we return here???	fprintf(stderr, "Wrong number of wnd_init_option_ %d\n", 		wnd_init_option_);	abort();	return (2.0); // XXX make msvc happy.}/* * Dupack-action: what to do on a DUP ACK.  After the initial check * of 'recover' below, this function implements the following truth * table: * *	bugfix	ecn	last-cwnd == ecn	action * *	0	0	0			tahoe_action *	0	0	1			tahoe_action	[impossible] *	0	1	0			tahoe_action *	0	1	1			slow-start, return *	1	0	0			nothing *	1	0	1			nothing		[impossible] *	1	1	0			nothing *	1	1	1			slow-start, return *//*  * A first or second duplicate acknowledgement has arrived, and * singledup_ is enabled. * If the receiver's advertised window permits, and we are exceeding our * congestion window by less than numdupacks_, then send a new packet. */voidTcpAgent::send_one(){	if (t_seqno_ <= highest_ack_ + wnd_ && t_seqno_ < curseq_ &&		t_seqno_ <= highest_ack_ + cwnd_ + dupacks_ ) {		output(t_seqno_, 0);		if (QOption_)			process_qoption_after_send () ;		t_seqno_ ++ ;		// send_helper(); ??	}	return;}voidTcpAgent::dupack_action(){	int recovered = (highest_ack_ > recover_);	if (recovered || (!bug_fix_ && !ecn_)) {		goto tahoe_action;	}	if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {		last_cwnd_action_ = CWND_ACTION_DUPACK;		slowdown(CLOSE_CWND_ONE);		reset_rtx_timer(0,0);		return;	}	if (bug_fix_) {		/*		 * The line below, for "bug_fix_" true, avoids		 * problems with multiple fast retransmits in one		 * window of data. 		 */		return;	}tahoe_action:        recover_ = maxseq_;        if (!lossQuickStart()) {		// we are now going to fast-retransmit and willtrace that event		trace_event("FAST_RETX");		last_cwnd_action_ = CWND_ACTION_DUPACK;		slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_ONE);	}	reset_rtx_timer(0,0);	return;}/* * When exiting QuickStart, reduce the congestion window to the *   size that was actually used. */void TcpAgent::endQuickStart(){	qs_approved_ = 0;        qs_cwnd_ = 0;        qs_window_ = maxseq_;	int new_cwnd = maxseq_ - last_ack_;	if (new_cwnd > 1 && new_cwnd < cwnd_) {	 	cwnd_ = new_cwnd;		if (cwnd_ < initial_window()) 			cwnd_ = initial_window();	}}void TcpAgent::processQuickStart(Packet *pkt){	// QuickStart code from Srikanth Sundarrajan.	hdr_tcp *tcph = hdr_tcp::access(pkt);	hdr_qs *qsh = hdr_qs::access(pkt);	double now = Scheduler::instance().clock();	int app_rate;        // printf("flag: %d ttl: %d ttl_diff: %d rate: %d\n", qsh->flag(),	//     qsh->ttl(), ttl_diff_, qsh->rate());	qs_requested_ = 0;	qs_approved_ = 0;	if (qsh->flag() == QS_RESPONSE && qsh->ttl() == ttl_diff_ &&             qsh->rate() > 0) {                app_rate = (int) (hdr_qs::rate_to_Bps(qsh->rate()) *                      (now - tcph->ts_echo()) / (size_ + headersize()));#ifdef QS_DEBUG		printf("Quick Start approved, rate %d, window %d\n", 				     qsh->rate(), app_rate);#endif                if (app_rate > initial_window()) {			qs_cwnd_ = app_rate;                        qs_approved_ = 1;                }        } else { // Quick Start rejected#ifdef QS_DEBUG                printf("Quick Start rejected\n");#endif        }}/* * ACK has been received, hook from recv() */void TcpAgent::recv_frto_helper(Packet *pkt){	hdr_tcp *tcph = hdr_tcp::access(pkt);	if (tcph->seqno() == last_ack_ && frto_ != 0) {		/*		 * Duplicate ACK while in F-RTO indicates that the		 * timeout was valid. Go to slow start retransmissions.		 */		t_seqno_ = highest_ack_ + 1;		cwnd_ = frto_;		frto_ = 0;		// Must zero dupacks (in order to trigger send_much at recv)		// dupacks is increased in recv after exiting this function		dupacks_ = -1;	}}/* * A spurious timeout has been detected. Do appropriate actions. */void TcpAgent::spurious_timeout(){	frto_ = 0;	switch (spurious_response_) {	case 1:	default:		/*		 * Full revert of congestion window		 * (FlightSize before last acknowledgment)		 */		cwnd_ = t_seqno_ - prev_highest_ack_;		break; 	case 2:		/*		 * cwnd = reduced ssthresh (approx. half of the earlier pipe)		 */		cwnd_ = ssthresh_; break;	case 3:		/*		 * slow start, but without retransmissions		 */		cwnd_ = 1; break;	}	/*	 * Revert ssthresh to size before retransmission timeout	 */	ssthresh_ = pipe_prev_;	/* If timeout was spurious, bugfix is not needed */	recover_ = highest_ack_ - 1;}/* * Loss occurred in Quick-Start window. * If Quick-Start is enabled, packet loss in the QS phase should * trigger slow start instead of the regular fast retransmit, * see [draft-amit-quick-start-03.txt] (to appear). * We use variable tcp_qs_recovery_ to toggle this behaviour on and off. * If tcp_qs_recovery_ is true, initiate slow start to probe for * a correct window size. * * Return value: non-zero if Quick-Start specific loss recovery took place */int TcpAgent::lossQuickStart(){       if (qs_window_ && tcp_qs_recovery_) {                //recover_ = maxseq_;                //reset_rtx_timer(1,0);                slowdown(CLOSE_CWND_INIT);		// reset ssthresh to half of W-D/2?                qs_window_ = 0;                output(last_ack_ + 1, TCP_REASON_DUPACK);                return 1;

⌨️ 快捷键说明

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