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

📄 tcp.cc

📁 diff serve for ns-2, work for version 2.29
💻 CC
📖 第 1 页 / 共 5 页
字号:
         * 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;	if (cwnd_ < ssthresh_) {		/* slow-start (exponential) */		cwnd_ += 1;	} else {		/* linear */		double f;		switch (wnd_option_) {		case 0:			if (++count_ >= cwnd_) {				count_ = 0;				++cwnd_;			}			break;		case 1:			/* This is the standard algorithm. */			increment = increase_num_ / cwnd_;			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;}voidTcpAgent::slowdown(int how){	double decrease;  /* added for highspeed - sylvia */	double win, halfwin, decreasewin;	int slowstart = 0;	++ncwndcuts_;	if (!(how & TCP_IDLE) && !(how & NO_OUTSTANDING_DATA)){		++ncwndcuts1_; 	}	// we are in slowstart for sure if cwnd < ssthresh	if (cwnd_ < 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 && (cwnd_ > 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) && (cwnd_ > 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*cwnd_/4)			ssthresh_  = (int)(3*cwnd_/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) {			cwnd_ = halfwin;		} else cwnd_ = 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.                cwnd_ = decreasewin;                if (cwnd_ < 1)                        cwnd_ = 1;	}	else if (how & CLOSE_CWND_RESTART) 		cwnd_ = int(wnd_restart_);	else if (how & CLOSE_CWND_INIT)		cwnd_ = int(wnd_init_);	else if (how & CLOSE_CWND_ONE)		cwnd_ = 1;	else if (how & CLOSE_CWND_HALF_WAY) {		// cwnd_ = win - (win - W_used)/2 ;		cwnd_ = W_used + decrease_num_ * (win - W_used);                if (cwnd_ < 1)                        cwnd_ = 1;	}

⌨️ 快捷键说明

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