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

📄 tcp-fast.c

📁 fast_tcp的源代码加上了自己对它的中文注释
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************\
* TCP-FAST  NS2 Module                                         	*
* University of Melbourne April 2005                         		*
*                                                              	*
* Coding: Tony Cui and Lachlan Andrew                          	*
*                                                                      *
* Revision History                                                     *
* Version 1.1.3 (14 Jan, 2007)        					*
*     Make updating every other RTT the default, as in Linux		*
* Version 1.1.2                					*
*     Make FAST_CC_MIQ tunable						*
*     (using a mi_threshold_ (tunable TCL variable)  to replace it) 	*
*     Consider the calculation error when cwnd is an integer. Give	*
*     user 3 choices the calculate cwnd.(use integer without		*
*     considering calculation error (mode 0),  using integer 		*
*     with considering calculatioin error (mode 1) and using double	*
*     (mode 2).							*
*     Fix a bug in fast_cc: add acks_per_rtt++ in the function. 	*
*     Fix a bug in fast_cc: compare t_seqno and tcph->seqno() to       *
*     prevent t_seqno greater than tcph->seqno().			*
*     Allow user update cwnd every other rtt (default is every rtt)	*
* Version 1.1.1                                                        *
*     Set ECT bit correctly if ECN capable				*
* Version 1.1                                                          *
*     Add SACK function into Fast                                      *
*     Fix bug in output function which didn't consider SYN packets.    *
*     Fix bug in using INT_VARABLE_INVALID_VALUE instead of            *
*     DOUBLE_VARABLE_INVALID_VALUE                                     *
* Version 1.0.1 Released 13 November, 2004                             *
*     Fix bug in baseRTT_ estimation with pk loss                      *
* Version 1.0   Released 24 September, 2004                            *
\************************************************************************/

#ifndef lint
static const char rcsid[] =
"@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/tcp/tcp-fast.cc,v 1.35 2004/12/14 05:05:21 xuanc Exp $ (NCSU/IBM)";
#endif

#define FAST_ALLOW_CC 		0x1
#define FAST_ALLOW_MI		0x2
#define INT_VARABLE_INVALID_VALUE	999999999
#define DOUBLE_VARABLE_INVALID_VALUE 	99999999999.0

#include "ip.h"
#include "tcp.h"
#include "tcp-fast.h"
#include "flags.h"
#include "random.h"

/******************************************************************************/
static class FastTcpClass : public TclClass
{
	public:
		FastTcpClass() : TclClass("Agent/TCP/Fast") {}
		TclObject* create(int, const char*const*)
		{
			return (new FastTcpAgent());
		}
} class_fast;


/******************************************************************************/
FastTcpAgent::~FastTcpAgent()
{
#ifdef FASTTCPAGENT_DEBUG
	fclose(fasttcpagent_recordfps[0]);
	fclose(fasttcpagent_recordfps[1]);
#endif
	
	delete scb_;
	
	if (sendtime_)
		delete []sendtime_;
	if (transmits_)
		delete []transmits_;
	if (cwnd_array_)
		delete []cwnd_array_;
}

/******************************************************************************/
FastTcpAgent::FastTcpAgent() : TcpAgent(),
avgRTT_(0), baseRTT_(0), avg_cwnd_last_RTT_(1),
alpha_(0), beta_(0), fastrecov_(FALSE),
pipe_(-1), next_pkt_(0), firstpartial_(0),
last_natural_ack_number_(-1), on_first_rtt_(true),
gamma_(0.5),destine_pace(1000)
{
	sendtime_ = NULL;
	transmits_ = NULL;
	cwnd_array_ = NULL;
	bind_bool("partial_ack_", &partial_ack_);
	/* Use the Reassembly Queue based scoreboard as
	* ScoreBoard is O(cwnd) which is bad for HSTCP
	* scb_ = new ScoreBoard(new ScoreBoardNode[SBSIZE],SBSIZE);
	*/
	scb_ = new ScoreBoardRQ();
	
#ifdef TCP_DELAY_BIND_ALL
#else /* ! TCP_DELAY_BIND_ALL */
	/*bind tunable parameters*/
	bind("fast_update_cwnd_interval_", &cwnd_update_period_);
	bind("avg_cwnd_last_RTT_", &avg_cwnd_last_RTT_);
	bind("avgRTT_", &avgRTT_);
	bind("baseRTT_", &baseRTT_);
	bind("alpha_", &alpha_);
	bind("beta_", &beta_);
	bind("high_accuracy_cwnd_", &high_accuracy_cwnd_);
	bind("mi_threshold_", &mi_threshold_);
	
	//	bind("pipe_", &pipe_);		//weixl
	//	bind("sack_num_", &sack_num_);	//weixl
	//	bind("sack_len_", &sack_len_);  //weixl
	//	bind("alpha_tuning_", &alpha_tuning_);
	bind("gamma_", &gamma_);
#endif /* TCP_DELAY_BIND_ALL */
	
#ifdef FASTTCPAGENT_DEBUG
	static unsigned int s_agent_ID = 0;
	char strTmp[30];
	sprintf(strTmp, "agent%d_%s.txt", s_agent_ID, "record0");
	fasttcpagent_recordfps[0] = fopen(strTmp, "w+");
	sprintf(strTmp, "agent%d_%s.txt", s_agent_ID, "record1");
	fasttcpagent_recordfps[1] = fopen(strTmp, "w+");
	s_agent_ID++;
#endif
	
}

/******************************************************************************/
void
FastTcpAgent::delay_bind_init_all()
{
#ifdef TCP_DELAY_BIND_ALL
	// Defaults for bound variables should be set in ns-default.tcl.
	delay_bind_init_one("cwnd_update_period_");
	delay_bind_init_one("avg_cwnd_last_RTT_");
	delay_bind_init_one("avgRTT_");
	delay_bind_init_one("baseRTT_");
	delay_bind_init_one("alpha_");
	delay_bind_init_one("beta_");
	delay_bind_init_one("high_accuracy_cwnd_");
	delay_bind_init_one("mi_threshold_");
	
	//	delay_bind_init_one("pipe_"); 	//weixl
	//	delay_bind_init_one("sack_num_");//weixl
	//	delay_bind_init_one("sack_len_");
	//	delay_bind_init_one("alpha_tuning_");
	delay_bind_init_one("gamma_");
#endif /* TCP_DELAY_BIND_ALL */
	TcpAgent::delay_bind_init_all();
	
	reset();
}

/******************************************************************************/
int
FastTcpAgent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
{
#ifdef TCP_DELAY_BIND_ALL
	if (delay_bind(varName, localName, "cwnd_update_period_", &fast_update_cwnd_interval_, tracer))
		return TCL_OK;
	if (delay_bind(varName, localName, "avg_cwnd_last_RTT_", &avg_cwnd_last_RTT_, tracer))
		return TCL_OK;
	if (delay_bind(varName, localName, "avgRTT_", &avgRTT_, tracer))
		return TCL_OK;
	if (delay_bind(varName, localName, "baseRTT_", &baseRTT_, tracer))
		return TCL_OK;
	if (delay_bind(varName, localName, "alpha_", &alpha_, tracer))
		return TCL_OK;
	if (delay_bind(varName, localName, "beta_", &beta_, tracer))
		return TCL_OK;
	if (delay_bind(varName, localName, "gamma_", &gamma_, tracer))
		return TCL_OK;
	if (delay_bind(varName, localName, "high_accuracy_cwnd_", &high_accuracy_cwnd_, tracer))
		return TCL_OK;
	if (delay_bind(varName, localName, "mi_threshold_", &mi_threshold_, tracer))
		return TCL_OK;
	
	//	if (delay_bind(varName, localName, "pipe_", &pipe_, tracer))
	//		return TCL_OK;		//weixl
	//	if (delay_bind(varName, localName, "sack_num_", &sack_num_, tracer))
	//		return TCL_OK;		//weixl
	//        if (delay_bind(varName, localName, "sack_len_", &sack_len_, tracer))
	//                return TCL_OK;          //weixl
	//	if (delay_bind(varName, localName, "alpha_tuning_", &alpha_tuning_, tracer))
	//		return TCL_OK;
#endif /* TCP_DELAY_BIND_ALL */
	
	return TcpAgent::delay_bind_dispatch(varName, localName, tracer);
}

/******************************************************************************/
/* Print out just the variable that is modified */
void
FastTcpAgent::traceVar(TracedVar* v)
{
	double curtime;
	Scheduler& s = Scheduler::instance();
	char wrk[500];
	int n;
	
	curtime = &s ? s.clock() : 0;// 取得当前时间.
	if (!strcmp(v->name(), "avgRTT_")
		|| !strcmp(v->name(), "baseRTT_")
		|| !strcmp(v->name(), "mi_threshold_")
		)//v->name()返回的值是avgRTT_,baseRTT_,mi_threshold_其中之一
		sprintf(wrk,"%-8.5f %-2d %-2d %-2d %-2d %s %-6.3f",
		curtime, addr(), port(), daddr(), dport(),
		v->name(), double(*((TracedDouble*) v)));
	else if (!strcmp(v->name(), "avg_cwnd_last_RTT_")
		|| !strcmp(v->name(), "alpha_")
		|| !strcmp(v->name(), "beta_")
		|| !strcmp(v->name(), "high_accuracy_cwnd_" )
		)//v->name()返回的值是avg_cwnd_last_RTT_,alpha_,beta_,high_accuracy_cwnd_其中之一
		sprintf(wrk,"%-8.5f %-2d %-2d %-2d %-2d %s %d",
		curtime, addr(), port(), daddr(), dport(),
		v->name(), int(*((TracedInt*) v)));
	else//否则让父类作默认处理
	{
		TcpAgent::traceVar(v);
		return;
	}
	
	n = strlen(wrk);
	wrk[n] = '\n';
	wrk[n+1] = 0;
	if (channel_)
		(void)Tcl_Write(channel_, wrk, n+1);
	wrk[n] = 0;
	
	return;
}

/******************************************************************************/
void
FastTcpAgent::reset ()
{
	fast_opts = 0;
	fast_opts |= FAST_ALLOW_CC;
	fast_opts |= FAST_ALLOW_MI;
	cwnd_update_time = fasttime();		
	cwnd_increments = 0;
	firstrecv_ = -1.0;
	slowstart_ = 2;
	acks_per_rtt = 0;
	acks_last_rtt = 0;
	bc_ack = 0;
	bc_spacing = 0;
	t_backoff_=1;
	baseRTT_ = DOUBLE_VARABLE_INVALID_VALUE;
	newcwnd_ = DOUBLE_VARABLE_INVALID_VALUE;
	currentTime = 0;
	fast_calc_cwnd_end = 0;
	scb_->ClearScoreBoard();
	cwnd_remainder = 0;
	
	TcpAgent::reset ();
}

#define CWND_USE_INT	0
#define CWND_USE_INT_CONSIDER_ERROR	1
#define CWND_USE_DOUBLE	2
/******************************************************************************/
/*this function should be used to calculate the new cwnd_ size in every update*/
double
FastTcpAgent::fast_calc_cwnd(double cwnd,double old_cwnd)
{
	double q = avgRTT_ - baseRTT_;//平均每个包在路由的排队时间.
	double cwnd_array_q = old_cwnd * q;//窗口中的包发送完用于路由排队的时间
	double target_cwnd = cwnd;
	
	//double destine_alpha;
	if ( avgRTT_ == 0 || baseRTT_ == DOUBLE_VARABLE_INVALID_VALUE )		//重置或初始化
	{
		return cwnd;
	}
	
	if ( fast_opts & FAST_ALLOW_CC )		//fast_opts中设置了FAST_ALLOW_CC位
	{
		if ( cwnd_array_q < alpha_ * avgRTT_ ||
			cwnd_array_q >= beta_ * avgRTT_ )
		{
			// target_cwnd = (cwnd + old_cwnd * (baseRTT_/avgRTT_) + alpha_) / 2;
			target_cwnd = ( (1-gamma_) * cwnd + (old_cwnd * (baseRTT_/avgRTT_) + alpha_) * gamma_);
			//destine_alpha = q * destine_pace;
			//target_cwnd = ( (1-gamma_) * cwnd + (old_cwnd * (baseRTT_/avgRTT_) + destine_alpha) * gamma_);
			
			double gamma=gamma_;
			double alpha=alpha_;
			double beta=beta_;
			//printf("gamma:%lf alpha;%lf beta:%lf target:%lf, now:%lf, new:%lf\n", gamma, alpha, beta, (old_cwnd * (baseRTT_/avgRTT_) + alpha_), cwnd, target_cwnd);
			if (target_cwnd<2)
				target_cwnd=2;
			
			/*因为网络中窗口定义是整型,而为了计算的精度用了双精度数.
			*所以将每次的小数部分计合下来,满1时加到窗口计算值中*/
			if ( high_accuracy_cwnd_ == CWND_USE_INT_CONSIDER_ERROR ||
				high_accuracy_cwnd_ == CWND_USE_INT )	//we use intergal to store cwnd.
			{
				if (high_accuracy_cwnd_ == CWND_USE_INT_CONSIDER_ERROR)	//we consider the calculation error.
				{
					cwnd_remainder += (target_cwnd - (int)target_cwnd);
					if (cwnd_remainder > 1)
					{
						target_cwnd++;
						cwnd_remainder--;
					}
				}
				target_cwnd = (int)target_cwnd;
				//printf("gamma:%lf alpha;%lf beta:%lf target:%lf, now:%lf, new:%lf\n", gamma, alpha, beta, (old_cwnd * (baseRTT_/avgRTT_) + alpha_), cwnd, target_cwnd);
			}
		}
	}	
	return target_cwnd;
}

/******************************************************************************/
/* in this function, we can get the new average rtt which */
/* will be used to get the new cwnd_ size */
/*用于计算包平均返回时间*/
double
FastTcpAgent::fast_est_update_avgrtt(double rtt)
{
	double scale = avg_cwnd_last_RTT_/3;	
	double avgRTT=avgRTT_;
	if ( !avgRTT)		//首个包返回
		avgRTT = rtt;
	else if ( scale > 256 )
	{
		avgRTT = ((scale-1) * avgRTT + rtt)/scale;
	}
	else
	{
		avgRTT = (avgRTT*255 + rtt)/256;
	}
	return (double)avgRTT;
}

/******************************************************************************/
/* We get average cwnd size which will be used as a history record. */
double
FastTcpAgent::fast_est_update_avg_cwnd(int inst_cwnd)
{
#if 0
	unsigned int scale = avg_cwnd_last_RTT_/3;
	double avg_cwnd=avg_cwnd_last_RTT_;
	
	if ( !avg_cwnd)
		avg_cwnd = inst_cwnd;
	else if ( scale > 256 )
	{
		avg_cwnd = ((scale-1) * avg_cwnd + inst_cwnd)/scale;
	}
	else
	{
		avg_cwnd = (avg_cwnd*255 + inst_cwnd)/256;
	}
	return avg_cwnd;

⌨️ 快捷键说明

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