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

📄 tcp.cc

📁 这个是目前国际上比较怪异的一种长距离高带宽环境下的拥塞控制算法
💻 CC
📖 第 1 页 / 共 4 页
字号:
	int temp;	if (cwnd_ < ssthresh_) {		/* slow-start (exponential) */		cwnd_ += 1; dl_count_=0; dl_mode_=1;	} else {		/* linear */		dl_mode_=2;		if (wnd_option_ < 0) 		   temp=-wnd_option_;		else		   temp=wnd_option_;		switch (temp) {		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. */			f = (t_srtt_ >> T_SRTT_BITS) * tcp_tick_;			f *= f;			f *= wnd_const_;			f += fcnt_;			if (f > cwnd_) {				fcnt_ = 0;				++cwnd_;			} else				fcnt_ = f;			break;		case 3:			f = awnd_;			f *= f;			f *= wnd_const_;			f += fcnt_;			if (f > cwnd_) {				fcnt_ = 0;				++cwnd_;			} else				fcnt_ = f;			break;		case 4:				f = awnd_;				f *= wnd_const_;				f += fcnt_;				if (f > cwnd_) {						fcnt_ = 0;						++cwnd_;				} else						fcnt_ = f;				break;		case 5:						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 */			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;		case 10:		   /* H-TCP continuous */			dl_count_+=1.0 / cwnd_; 			RTT_Scaling = dl_minrtt_*tcp_tick_/0.1;			if (RTT_Scaling < 0.1) RTT_Scaling = 0.1;			if (RTT_Scaling >2) RTT_Scaling=2; 			diff = dl_count_*dl_minrtt_*tcp_tick_-1.0; 			if (diff<0.0) 			   f=1;			else {                   			   f= 1+10*diff+(diff/2)*(diff/2);			   f= f*RTT_Scaling;			   if (f<1) f=1; // ensure RTT scaling doesn't lead to unfairness against standard AIMD			}			f = f*(1-decrease_num_)/(1-0.5);			dl_alpha_=f;			cwnd_+=f/cwnd_;						break;		case 11:			/* This is the standard algorithm with adaptive backoff. */			increment = increase_num_/ cwnd_;			dl_count_+=1.0 / cwnd_; 			if (wnd_option_<0) 			   increment *= (1-decrease_num_)/(1-0.5);			dl_alpha_=increment*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;		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, xx, prev_cwnd_;	int slowstart = 0;	++ncwndcuts_;			// 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 {			if (wnd_option_ < 0) {			   double thresh=0.2;			   cwnd_ -= dl_alpha_-1; //account for overshoot due to delay in detecting congestion			   if ( (dl_maxB_ > (1-thresh)*dl_oldmaxB_)&&(dl_maxB_ < (1+thresh)*dl_oldmaxB_) ) {				  dl_modecount_ ++;				  if (dl_modecount_ > 1 && dl_maxrtt_>0)					 decrease_num_ = dl_minrtt_/dl_maxrtt_;				  else					 decrease_num_ = 0.5;            			   } else {				  dl_modecount_ = 0;				  decrease_num_ = 0.5;			   }			   if (decrease_num_ <0.5) decrease_num_=0.5;			   if (decrease_num_ >0.8) decrease_num_=0.8;                     			   dl_oldmaxB_ = dl_maxB_;			   // add slowly fading memory for maxRTT to accommodate routing changes etc			   if (dl_minrtt_ > 0 && dl_maxrtt_ > dl_minrtt_)				  dl_maxrtt_ = dl_minrtt_ + ((dl_maxrtt_-dl_minrtt_)*95)/100;			}			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; dl_modecount_=0;		} 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  || how & SOFT_CLOSE_CWND)		// 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;	}	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");	dl_count_=0; dl_mode_=0; }/* * Process a packet that acks previously unacknowleged data. */void TcpAgent::newack(Packet* pkt){	double now = Scheduler::instance().clock();	int rtt;	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_)			rtt_update(now - tcph->ts_echo());		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_;	dl_rtti_ = (now - tcph->ts_echo());	if (dl_rtti_/tcp_tick_ < dl_minrtt_) dl_minrtt_= dl_rtti_/tcp_tick_; 	rtt= int(t_srtt_)>>3;	if (!first_decrease_ && rtt > dl_maxrtt_) dl_maxrtt_= rtt;  // max smoothed rtt ok with delayed acking		if (dl_mode_>0)	   dl_packetcount_+=(highest_ack_ -prev_highest_ack_);	else {	   //during backoff phase	   dl_thresh_=now;	   dl_packetcount_=0;	}    	if (dl_packetcount_ >= int(cwnd_- dl_alpha_) && now-dl_thresh_ >= dl_minrtt_*tcp_tick_ ) {	   if (dl_count_ <=3 && cwnd_ >= ssthresh_) {		   //congestion avoidance and just after backoff		  dl_Bi_=dl_packetcount_/(now-dl_thresh_);		  dl_minB_ = (cwnd_ - dl_alpha_)/(dl_minrtt_*tcp_tick_);		  dl_maxB_=dl_Bi_;	   } else {		  dl_Bi_=0.75*dl_Bi_+0.25*dl_packetcount_/(now-dl_thresh_); //useful with delayed acking		  //dl_Bi_=dl_packetcount_/(now-dl_thresh_);		  if (dl_Bi_ > dl_maxB_) dl_maxB_=dl_Bi_;	   }	   dl_thresh_=now;	   dl_packetcount_=0;	}}/* * 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 (!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();	}}/* * Set the initial window.  */doubleTcpAgent::initial_window(){	//	// 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;

⌨️ 快捷键说明

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