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

📄 tcp.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
📖 第 1 页 / 共 5 页
字号:
		 * Another way to do the same thing is to open one tcp		 * object and use start/stop/maxpkts_ or advanceby to control		 * how much data is sent in each burst.		 * With a single connection, slow_start_restart_		 * should be configured as desired.		 *		 * This implementation (persist) may not correctly		 * emulate pure-BSD-based systems which close cwnd		 * after the connection goes idle (slow-start		 * restart).  See appendix C in		 * Jacobson and Karels ``Congestion		 * Avoidance and Control'' at		 * <ftp://ftp.ee.lbl.gov/papers/congavoid.ps.Z>		 * (*not* the original		 * '88 paper) for why BSD does this.  See		 * ``Performance Interactions Between P-HTTP and TCP		 * Implementations'' in CCR 27(2) for descriptions of		 * what other systems do the same.		 *		 */		if (strcmp(argv[1], "persist") == 0) {			TcpAgent *other			  = (TcpAgent*)TclObject::lookup(argv[2]);			cwnd_ = other->cwnd_;			awnd_ = other->awnd_;			ssthresh_ = other->ssthresh_;			t_rtt_ = other->t_rtt_;			t_srtt_ = other->t_srtt_;			t_rttvar_ = other->t_rttvar_;			t_backoff_ = other->t_backoff_;			return (TCL_OK);		}	}	return (Agent::command(argc, argv));}/* * Returns the window size adjusted to allow <num> segments past recovery * point to be transmitted on next ack. */int TcpAgent::force_wnd(int num){	return recover_ + num - (int)highest_ack_;}int TcpAgent::window(){        /*         * If F-RTO is enabled and first ack has come in, temporarily open         * window for sending two segments.	 * The F-RTO code is from Pasi Sarolahti.  F-RTO is an algorithm	 * for detecting spurious retransmission timeouts.         */        if (frto_ == 2) {                return (force_wnd(2) < wnd_ ?                        force_wnd(2) : (int)wnd_);        } else {		return (cwnd_ < wnd_ ? (int)cwnd_ : (int)wnd_);        }}double TcpAgent::windowd(){	return (cwnd_ < wnd_ ? (double)cwnd_ : (double)wnd_);}/* * Try to send as much data as the window will allow.  The link layer will  * do the buffering; we ask the application layer for the size of the packets. */void TcpAgent::send_much(int force, int reason, int maxburst){	send_idle_helper();	int win = window();	int npackets = 0;	if (!force && delsnd_timer_.status() == TIMER_PENDING)		return;	/* Save time when first packet was sent, for newreno  --Allman */	if (t_seqno_ == 0)		firstsent_ = Scheduler::instance().clock();	if (burstsnd_timer_.status() == TIMER_PENDING)		return;	while (t_seqno_ <= highest_ack_ + win && t_seqno_ < curseq_) {		if (overhead_ == 0 || force || qs_approved_) {			output(t_seqno_, reason);			npackets++;			if (QOption_)				process_qoption_after_send () ; 			t_seqno_ ++ ;			if (qs_approved_ == 1) {				// delay = effective RTT / window				double delay = (double) t_rtt_ * tcp_tick_ / win;				if (overhead_) { 					delsnd_timer_.resched(delay + Random::uniform(overhead_));				} else {					delsnd_timer_.resched(delay);				}				return;			}		} else if (!(delsnd_timer_.status() == TIMER_PENDING)) {			/*			 * Set a delayed send timeout.			 */			delsnd_timer_.resched(Random::uniform(overhead_));			return;		}		win = window();		if (maxburst && npackets == maxburst)			break;	}	/* call helper function */	send_helper(maxburst);}/* * We got a timeout or too many duplicate acks.  Clear the retransmit timer.   * Resume the sequence one past the last packet acked.   * "mild" is 0 for timeouts and Tahoe dup acks, 1 for Reno dup acks. * "backoff" is 1 if the timer should be backed off, 0 otherwise. */void TcpAgent::reset_rtx_timer(int mild, int backoff){	if (backoff)		rtt_backoff();	set_rtx_timer();	if (!mild)		t_seqno_ = highest_ack_ + 1;	rtt_active_ = 0;}/* * Set retransmit timer using current rtt estimate.  By calling resched(),  * it does not matter whether the timer was already running. */void TcpAgent::set_rtx_timer(){	rtx_timer_.resched(rtt_timeout());}/* * Set new retransmission timer if not all outstanding * or available data acked, or if we are unable to send because  * cwnd is less than one (as when the ECN bit is set when cwnd was 1). * Otherwise, if a timer is still outstanding, cancel it. */void TcpAgent::newtimer(Packet* pkt){	hdr_tcp *tcph = hdr_tcp::access(pkt);	/*	 * t_seqno_, the next packet to send, is reset (decreased) 	 *   to highest_ack_ + 1 after a timeout,	 *   so we also have to check maxseq_, the highest seqno sent.	 * In addition, if the packet sent after the timeout has	 *   the ECN bit set, then the returning ACK caused cwnd_ to	 *   be decreased to less than one, and we can't send another	 *   packet until the retransmit timer again expires.	 *   So we have to check for "cwnd_ < 1" as well.	 */	if (t_seqno_ > tcph->seqno() || tcph->seqno() < maxseq_ || cwnd_ < 1) 		set_rtx_timer();	else		cancel_rtx_timer();}/* * for experimental, high-speed TCP */double TcpAgent::linear(double x, double x_1, double y_1, double x_2, double y_2){	// The y coordinate factor ranges from y_1 to y_2	//  as the x coordinate ranges from x_1 to x_2.	double y = y_1 + ((y_2 - y_1) * ((x - x_1)/(x_2-x_1)));	return y;}/* * Limited Slow-Start for large congestion windows. * This is only used when max_ssthresh_ is non-zero. */double TcpAgent::limited_slow_start(double cwnd, double max_ssthresh, double increment){	int round = int(cwnd / (double(max_ssthresh)/2.0));	double increment1 = 1.0/(double(round)); 	if (increment < increment1)		increment = increment1;	return increment;}/* * For retrieving numdupacks_. */int TcpAgent::numdupacks(double cwnd){        int cwndfraction = (int) cwnd/numdupacksFrac_;	if (numdupacks_ > cwndfraction) {	  	return numdupacks_;        } else {	  	return cwndfraction;	}}/* * Calculating the decrease parameter for highspeed TCP. */double TcpAgent::decrease_param(){	double decrease;	// OLD:	// decrease = linear(log(cwnd_), log(low_window_), 0.5, log(high_window_), high_decrease_);	// NEW (but equivalent):        decrease = hstcp_.dec1 + log(cwnd_) * hstcp_.dec2;  	return decrease;}/* * Calculating the increase parameter for highspeed TCP. */double TcpAgent::increase_param(){	double increase, decrease, p, answer;	/* extending the slow-start for high-speed TCP */	/* for highspeed TCP -- from Sylvia Ratnasamy, */	/* modifications by Sally Floyd and Evandro de Souza */ 	// p ranges from 1.5/W^2 at congestion window low_window_, to	//    high_p_ at congestion window high_window_, on a log-log scale.        // The decrease factor ranges from 0.5 to high_decrease	//  as the window ranges from low_window to high_window, 	//  as the log of the window. 	// For an efficient implementation, this would just be looked up	//   in a table, with the increase and decrease being a function of the	//   congestion window.       if (cwnd_ <= low_window_) { 		answer = 1 / cwnd_;       		return answer;        } else if (cwnd_ >= hstcp_.cwnd_last_ && 	      cwnd_ < hstcp_.cwnd_last_ + cwnd_range_) {	      // cwnd_range_ can be set to 0 to be disabled,	      //  or can be set from 1 to 100        		answer = hstcp_.increase_last_ / cwnd_;              	return answer;       } else { 		// OLD: 		// p = exp(linear(log(cwnd_), log(low_window_), log(hstcp_.low_p), log(high_window_), log(high_p_)));		// NEW, but equivalent:        	p = exp(hstcp_.p1 + log(cwnd_) * hstcp_.p2);          	decrease = decrease_param();		// OLD:		// increase = cwnd_*cwnd_*p *(2.0*decrease)/(2.0 - decrease); 		// NEW, but equivalent:		increase = cwnd_ * cwnd_ * p /(1/decrease - 0.5);		//	if (increase > max_increase) { 		//		increase = max_increase;		//	} 		answer = increase / cwnd_;		hstcp_.cwnd_last_ = cwnd_;		hstcp_.increase_last_ = increase;       		return answer; 	}       }/* * open up the congestion window  */void TcpAgent::opencwnd() {	double increment;	Scheduler& s = Scheduler::instance();	double curtime;	curtime = &s ? s.clock() : 0;       	if (cwnd_ < ssthresh_) {		/* slow-start (exponential) */		// cwnd_ += 1;//printf("wnd_option_:%d maxcwnd_:%d,afew_:%d  ",wnd_option_,maxcwnd_,afew_);//printf("%-8.5f %6.3f %6.3f\n",curtime ,rts_retry,double(cwnd_));if(afew_==0)	cwnd_ += increase_num_; // ktnahm to suppress slow-start with TCP FeWelse {//add by chen	if(cwnd_<6)	{		if(rts_retry<=0.3) cwnd_ +=0.05;		else if((rts_retry>0.3) && (rts_retry<=0.6)) cwnd_ +=0.001; 		else if((rts_retry>0.6) && (rts_retry<1.7))  cwnd_ +=0.0;		else cwnd_ +=0.00;//		printf("%f\n",rts_retry);	}	// else printf("%f\n",rts_retry);//add end}	} else {		/* linear */		double f;		switch (wnd_option_) {		case 0:			if (++count_ >= cwnd_) {				count_ = 0;				++cwnd_;			}			break;		case 1:			/* This is the standard algorithm. *///printf("%f  ",tmpwnd);			if(afew_==0) 	increment = increase_num_ / cwnd_;			else			{			if(rts_retry<=0.3) increment=0.03 / cwnd_;			else if((rts_retry>0.3) && (rts_retry<=0.6)) 					increment=0.001 / cwnd_; 			else if((rts_retry>0.6) && (rts_retry<1.7))  					increment=0.0 / cwnd_;			else increment=0.0 / cwnd_;			if(cwnd_>=6) {increment=0; 				//	printf("%f\n",rts_retry);					}						}			if ((last_cwnd_action_ == 0 ||			  last_cwnd_action_ == CWND_ACTION_TIMEOUT) 			  && max_ssthresh_ > 0) {				increment = limited_slow_start(cwnd_,				  max_ssthresh_, increment);			}			cwnd_ += increment;			break;		case 2:			/* These are window increase algorithms			 * for experimental purposes only. */			/* This is the Constant-Rate increase algorithm                          *  from the 1991 paper by S. Floyd on "Connections  			 *  with Multiple Congested Gateways". 			 *  The window is increased by roughly 			 *  wnd_const_*RTT^2 packets per round-trip time.  */			f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;			f *= f;			f *= wnd_const_;			/* f = wnd_const_ * RTT^2 */			f += fcnt_;			if (f > cwnd_) {				fcnt_ = 0;				++cwnd_;			} else				fcnt_ = f;			break;		case 3:			/* The window is increased by roughly 			 *  awnd_^2 * wnd_const_ packets per RTT,			 *  for awnd_ the average congestion window. */			f = awnd_;			f *= f;			f *= wnd_const_;			f += fcnt_;			if (f > cwnd_) {				fcnt_ = 0;				++cwnd_;			} else				fcnt_ = f;			break;                case 4:			/* The window is increased by roughly 			 *  awnd_ * wnd_const_ packets per RTT,			 *  for awnd_ the average congestion window. */                        f = awnd_;                        f *= wnd_const_;                        f += fcnt_;                        if (f > cwnd_) {                                fcnt_ = 0;                                ++cwnd_;                        } else                                fcnt_ = f;                        break;		case 5:			/* The window is increased by roughly wnd_const_*RTT 			 *  packets per round-trip time, as discussed in			 *  the 1992 paper by S. Floyd on "On Traffic 			 *  Phase Effects in Packet-Switched Gateways". */                        f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;                        f *= wnd_const_;                        f += fcnt_;                        if (f > cwnd_) {                                fcnt_ = 0;                                ++cwnd_;                        } else                                fcnt_ = f;                        break;                case 6:                        /* binomial controls */                         cwnd_ += increase_num_ / (cwnd_*pow(cwnd_,k_parameter_));                                        break;  		case 8: 			/* high-speed TCP, RFC 3649 */			increment = increase_param();			if ((last_cwnd_action_ == 0 ||			  last_cwnd_action_ == CWND_ACTION_TIMEOUT) 			  && max_ssthresh_ > 0) {				increment = limited_slow_start(cwnd_,				  max_ssthresh_, increment);			}			cwnd_ += increment;                        break;		default:#ifdef notdef			/*XXX*/			error("illegal window option %d", wnd_option_);#endif			abort();		}	}	// if maxcwnd_ is set (nonzero), make it the cwnd limit	if (maxcwnd_ && (int(cwnd_) > maxcwnd_))		cwnd_ = maxcwnd_;	return;}void

⌨️ 快捷键说明

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