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

📄 tcp.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
📖 第 1 页 / 共 5 页
字号:
TcpAgent::slowdown(int how){	double decrease;  /* added for highspeed - sylvia */	double win, halfwin, decreasewin;	double ctemp_ = cwnd_; // ktnahm for monitoring convenience	int slowstart = 0;	++ncwndcuts_;	if (!(how & TCP_IDLE) && !(how & NO_OUTSTANDING_DATA)){		++ncwndcuts1_; 	}	// we are in slowstart for sure if cwnd < ssthresh	if (ctemp_ < ssthresh_) 		slowstart = 1;        if (precision_reduce_) {		halfwin = windowd() / 2;                if (wnd_option_ == 6) {                                 /* binomial controls */                        decreasewin = windowd() - (1.0-decrease_num_)*pow(windowd(),l_parameter_);                } else if (wnd_option_ == 8 && (ctemp_ > low_window_)) {                         /* experimental highspeed TCP */			decrease = decrease_param();			//if (decrease < 0.1) 			//	decrease = 0.1;			decrease_num_ = decrease;                        decreasewin = windowd() - (decrease * windowd());                } else {	 		decreasewin = decrease_num_ * windowd();		}		win = windowd();	} else  {		int temp;		temp = (int)(window() / 2);		halfwin = (double) temp;                if (wnd_option_ == 6) {                        /* binomial controls */                        temp = (int)(window() - (1.0-decrease_num_)*pow(window(),l_parameter_));                } else if ((wnd_option_ == 8) && (ctemp_ > low_window_)) {                         /* experimental highspeed TCP */			decrease = decrease_param();			//if (decrease < 0.1)                        //       decrease = 0.1;					decrease_num_ = decrease;                        temp = (int)(windowd() - (decrease * windowd()));                } else { 			temp = (int)(decrease_num_ * window());		}		decreasewin = (double) temp;		win = (double) window();	}	if (how & CLOSE_SSTHRESH_HALF)		// For the first decrease, decrease by half		// even for non-standard values of decrease_num_.		if (first_decrease_ == 1 || slowstart ||			last_cwnd_action_ == CWND_ACTION_TIMEOUT) {			// Do we really want halfwin instead of decreasewin		// after a timeout?			ssthresh_ = (int) halfwin;		} else {			ssthresh_ = (int) decreasewin;		}        else if (how & THREE_QUARTER_SSTHRESH)		if (ssthresh_ < 3*ctemp_/4)			ssthresh_  = (int)(3*ctemp_/4);	if (how & CLOSE_CWND_HALF)		// For the first decrease, decrease by half		// even for non-standard values of decrease_num_.		if (first_decrease_ == 1 || slowstart || decrease_num_ == 0.5) {			ctemp_ = halfwin;		} else ctemp_ = decreasewin;        else if (how & CWND_HALF_WITH_MIN) {		// We have not thought about how non-standard TCPs, with		// non-standard values of decrease_num_, should respond		// after quiescent periods.                ctemp_ = decreasewin;                if (ctemp_ < 1)                        ctemp_ = 1;	}	else if (how & CLOSE_CWND_RESTART) 		ctemp_ = int(wnd_restart_);	else if (how & CLOSE_CWND_INIT)		ctemp_ = int(wnd_init_);	else if (how & CLOSE_CWND_ONE)		ctemp_ = 1;	else if (how & CLOSE_CWND_HALF_WAY) {		// cwnd_ = win - (win - W_used)/2 ;		ctemp_ = W_used + decrease_num_ * (win - W_used);                if (ctemp_ < 1)                        ctemp_ = 1;	}	// ktnahm recover	if ( ctemp_ < 1 )   // ktnahm: min. cwnd_ is set to 1 now		ctemp_ = 1;	cwnd_ = ctemp_;	if (ssthresh_ < 2 && increase_num_ >= 1.0) // ktnahm mod		ssthresh_ = 2;	if (ssthresh_ < 0)		ssthresh_ = 0;   // ktnahm add	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)	if ( (cwnd_ == 1 && increase_num_ >= 1.0) || slowstart ) // ktnahm		// 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 (cwnd_ <= 1.0 && increase_num_ >= 1.0) { // ktnahm change for FeW			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()));

⌨️ 快捷键说明

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