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

📄 tcp.cc

📁 diff serve for ns-2, work for version 2.29
💻 CC
📖 第 1 页 / 共 5 页
字号:
	T_start = now ; 	RTT_count = 0 ; 	RTT_prev = 0 ; 	RTT_goodcount = 1 ; 	F_counting = 0 ; 	W_timed = -1 ; 	F_full = 0 ;	Backoffs = 0 ; }voidTcpAgent::reset(){	rtt_init();	rtt_seq_ = -1;	/*XXX lookup variables */	dupacks_ = 0;	curseq_ = 0;	set_initial_window();	t_seqno_ = 0;	maxseq_ = -1;	last_ack_ = -1;	highest_ack_ = -1;	ssthresh_ = int(wnd_);	if (max_ssthresh_ > 0 && max_ssthresh_ < ssthresh_) 		ssthresh_ = max_ssthresh_;	wnd_restart_ = 1.;	awnd_ = wnd_init_ / 2.0;	recover_ = 0;	closed_ = 0;	last_cwnd_action_ = 0;	boot_time_ = Random::uniform(tcp_tick_);	first_decrease_ = 1;	/* W.N.: for removing packets from previous incarnations */	lastreset_ = Scheduler::instance().clock();	/* Now these variables will be reset 	   - Debojyoti Dutta 12th Oct'2000 */ 	ndatapack_ = 0;	ndatabytes_ = 0;	nackpack_ = 0;	nrexmitbytes_ = 0;	nrexmit_ = 0;	nrexmitpack_ = 0;	necnresponses_ = 0;	ncwndcuts_ = 0;	ncwndcuts1_ = 0;	if (control_increase_) {		prev_highest_ack_ = highest_ack_ ; 	}	if (wnd_option_ == 8) {		// HighSpeed TCP		hstcp_.low_p = 1.5/(low_window_*low_window_);		double highLowWin = log(high_window_)-log(low_window_);		double highLowP = log(high_p_) - log(hstcp_.low_p);		hstcp_.dec1 = 		   0.5 - log(low_window_) * (high_decrease_ - 0.5)/highLowWin;		hstcp_.dec2 = (high_decrease_ - 0.5)/highLowWin;        	hstcp_.p1 = 		  log(hstcp_.low_p) - log(low_window_) * highLowP/highLowWin;		hstcp_.p2 = highLowP/highLowWin;	}	if (QOption_) {		int now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);		T_last = now ; 		T_prev = now ; 		W_used = 0 ;		if (EnblRTTCtr_) {			reset_qoption();		}	}}/* * Initialize variables for the retransmit timer. */void TcpAgent::rtt_init(){	t_rtt_ = 0;	t_srtt_ = int(srtt_init_ / tcp_tick_) << T_SRTT_BITS;	t_rttvar_ = int(rttvar_init_ / tcp_tick_) << T_RTTVAR_BITS;	t_rtxcur_ = rtxcur_init_;	t_backoff_ = 1;}double TcpAgent::rtt_timeout(){	double timeout;	if (rfc2988_) {	// Correction from Tom Kelly to be RFC2988-compliant, by	// clamping minrto_ before applying t_backoff_.		if (t_rtxcur_ < minrto_)			timeout = minrto_ * t_backoff_;		else			timeout = t_rtxcur_ * t_backoff_;	} else {		timeout = t_rtxcur_ * t_backoff_;		if (timeout < minrto_)			timeout = minrto_;	}	if (timeout > maxrto_)		timeout = maxrto_;        if (timeout < 2.0 * tcp_tick_) {		if (timeout < 0) {			fprintf(stderr, "TcpAgent: negative RTO!  (%f)\n",				timeout);			exit(1);		}		timeout = 2.0 * tcp_tick_;	}	return (timeout);}/* This has been modified to use the tahoe code. */void TcpAgent::rtt_update(double tao){	double now = Scheduler::instance().clock();	if (ts_option_)		t_rtt_ = int(tao /tcp_tick_ + 0.5);	else {		double sendtime = now - tao;		sendtime += boot_time_;		double tickoff = fmod(sendtime, tcp_tick_);		t_rtt_ = int((tao + tickoff) / tcp_tick_);	}	if (t_rtt_ < 1)		t_rtt_ = 1;	//	// t_srtt_ has 3 bits to the right of the binary point	// t_rttvar_ has 2        // Thus "t_srtt_ >> T_SRTT_BITS" is the actual srtt,   	//   and "t_srtt_" is 8*srtt.	// Similarly, "t_rttvar_ >> T_RTTVAR_BITS" is the actual rttvar,	//   and "t_rttvar_" is 4*rttvar.	//        if (t_srtt_ != 0) {		register short delta;		delta = t_rtt_ - (t_srtt_ >> T_SRTT_BITS);	// d = (m - a0)		if ((t_srtt_ += delta) <= 0)	// a1 = 7/8 a0 + 1/8 m			t_srtt_ = 1;		if (delta < 0)			delta = -delta;		delta -= (t_rttvar_ >> T_RTTVAR_BITS);		if ((t_rttvar_ += delta) <= 0)	// var1 = 3/4 var0 + 1/4 |d|			t_rttvar_ = 1;	} else {		t_srtt_ = t_rtt_ << T_SRTT_BITS;		// srtt = rtt		t_rttvar_ = t_rtt_ << (T_RTTVAR_BITS-1);	// rttvar = rtt / 2	}	//	// Current retransmit value is 	//    (unscaled) smoothed round trip estimate	//    plus 2^rttvar_exp_ times (unscaled) rttvar. 	//	t_rtxcur_ = (((t_rttvar_ << (rttvar_exp_ + (T_SRTT_BITS - T_RTTVAR_BITS))) +		t_srtt_)  >> T_SRTT_BITS ) * tcp_tick_;	return;}void TcpAgent::rtt_backoff(){	if (t_backoff_ < 64)		t_backoff_ <<= 1;	if (t_backoff_ > 8) {		/*		 * If backed off this far, clobber the srtt		 * value, storing it in the mean deviation		 * instead.		 */		t_rttvar_ += (t_srtt_ >> T_SRTT_BITS);		t_srtt_ = 0;	}}/* * headersize: *      how big is an IP+TCP header in bytes; include options such as ts * this function should be virtual so others (e.g. SACK) can override */int TcpAgent::headersize(){        int total = tcpip_base_hdr_size_;	if (total < 1) {		fprintf(stderr,		  "TcpAgent(%s): warning: tcpip hdr size is only %d bytes\n",		  name(), tcpip_base_hdr_size_);	}	if (ts_option_)		total += ts_option_size_;        return (total);}void TcpAgent::output(int seqno, int reason){	int force_set_rtx_timer = 0;	Packet* p = allocpkt();	hdr_tcp *tcph = hdr_tcp::access(p);	hdr_flags* hf = hdr_flags::access(p);	hdr_ip *iph = hdr_ip::access(p);	int databytes = hdr_cmn::access(p)->size();	tcph->seqno() = seqno;	tcph->ts() = Scheduler::instance().clock();	int is_retransmit = (seqno < maxseq_); 	// Mark packet for diagnosis purposes if we are in Quick-Start Phase	if (qs_approved_) {		hf->qs() = 1;	}         // store timestamps, with bugfix_ts_.  From Andrei Gurtov. 	// (A real TCP would use scoreboard for this.)        if (bugfix_ts_ && tss==NULL) {                tss = (double*) calloc(tss_size_, sizeof(double));                if (tss==NULL) exit(1);        }        //dynamically grow the timestamp array if it's getting full        if (bugfix_ts_ && window() > tss_size_* 0.9) {                double *ntss;                ntss = (double*) calloc(tss_size_*2, sizeof(double));                printf("resizing timestamp table\n");                if (ntss == NULL) exit(1);                for (int i=0; i<tss_size_; i++)                        ntss[(highest_ack_ + i) % (tss_size_ * 2)] =                                tss[(highest_ack_ + i) % tss_size_];                free(tss);                tss_size_ *= 2;                tss = ntss;        }         if (tss!=NULL)                tss[seqno % tss_size_] = tcph->ts(); 	tcph->ts_echo() = ts_peer_;	tcph->reason() = reason;        tcph->cwnd() = cwnd_;        tcph->t_rtt() = t_rtt_;	tcph->last_rtt() = int(int(t_rtt_)*tcp_tick_*1000);	if (ecn_) {		hf->ect() = 1;	// ECN-capable transport	}	if (cong_action_ && (!is_retransmit || SetCWRonRetransmit_)) {		hf->cong_action() = TRUE;  // Congestion action.		cong_action_ = FALSE;        }	/* Check if this is the initial SYN packet. */	if (seqno == 0) {		if (syn_) {			databytes = 0;			curseq_ += 1;			hdr_cmn::access(p)->size() = tcpip_base_hdr_size_;		}		if (ecn_) {			hf->ecnecho() = 1;//			hf->cong_action() = 1;			hf->ect() = 0;		}		if (qs_enabled_) {			hdr_qs *qsh = hdr_qs::access(p);			// dataout is kilobytes queued for sending			int dataout = (curseq_ - maxseq_ - 1) * (size_ + headersize()) / 1024;			int qs_rr = rate_request_;			if (qs_request_mode_ == 1) {				// PS: Avoid making unnecessary QS requests				// use a rough estimation of RTT in qs_rtt_				// to calculate the desired rate from dataout.				if (dataout * 1000 / qs_rtt_ < qs_rr) {					qs_rr = dataout * 1000 / qs_rtt_;				}				// qs_thresh_ is minimum number of unsent				// segments needed to activate QS request				if ((curseq_ - maxseq_ - 1) < qs_thresh_) {					qs_rr = 0;				}			}		    	if (qs_rr > 0) {				// QuickStart code from Srikanth Sundarrajan.				qsh->flag() = QS_REQUEST;				qsh->ttl() = Random::integer(256);				ttl_diff_ = (iph->ttl() - qsh->ttl()) % 256;				qsh->rate() = hdr_qs::Bps_to_rate(qs_rr * 1024);				qs_requested_ = 1;		    	} else {				qsh->flag() = QS_DISABLE;			}		}	}	else if (useHeaders_ == true) {		hdr_cmn::access(p)->size() += headersize();	}        hdr_cmn::access(p)->size();	/* if no outstanding data, be sure to set rtx timer again */	if (highest_ack_ == maxseq_)		force_set_rtx_timer = 1;	/* call helper function to fill in additional fields */	output_helper(p);        ++ndatapack_;        ndatabytes_ += databytes;	send(p, 0);	if (seqno == curseq_ && seqno > maxseq_)		idle();  // Tell application I have sent everything so far	if (seqno > maxseq_) {		maxseq_ = seqno;		if (!rtt_active_) {			rtt_active_ = 1;			if (seqno > rtt_seq_) {				rtt_seq_ = seqno;				rtt_ts_ = Scheduler::instance().clock();			}							}	} else {        	++nrexmitpack_;		nrexmitbytes_ += databytes;	}	if (!(rtx_timer_.status() == TIMER_PENDING) || force_set_rtx_timer)		/* No timer pending.  Schedule one. */		set_rtx_timer();}/* * Must convert bytes into packets for one-way TCPs. * If nbytes == -1, this corresponds to infinite send.  We approximate * infinite by a very large number (TCP_MAXSEQ). */void TcpAgent::sendmsg(int nbytes, const char* /*flags*/){	if (nbytes == -1 && curseq_ <= TCP_MAXSEQ)		curseq_ = TCP_MAXSEQ; 	else		curseq_ += (nbytes/size_ + (nbytes%size_ ? 1 : 0));	send_much(0, 0, maxburst_);}void TcpAgent::advanceby(int delta){  curseq_ += delta;	if (delta > 0)		closed_ = 0;	send_much(0, 0, maxburst_); }int TcpAgent::command(int argc, const char*const* argv){	if (argc == 3) {		if (strcmp(argv[1], "advance") == 0) {			int newseq = atoi(argv[2]);			if (newseq > maxseq_)				advanceby(newseq - curseq_);			else				advanceby(maxseq_ - curseq_);			return (TCL_OK);		}		if (strcmp(argv[1], "advanceby") == 0) {			advanceby(atoi(argv[2]));			return (TCL_OK);		}		if (strcmp(argv[1], "eventtrace") == 0) {			et_ = (EventTrace *)TclObject::lookup(argv[2]);			return (TCL_OK);		}		/*		 * Curtis Villamizar's trick to transfer tcp connection		 * parameters to emulate http persistent connections.		 *		 * 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(){        /*

⌨️ 快捷键说明

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