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

📄 tcp.cc

📁 Ns2 TCP 协议改进 版本 提高goodput
💻 CC
📖 第 1 页 / 共 5 页
字号:
#ifdef QS_DEBUG		printf("Quick Start approved, rate %d, window %d\n", 				     qsh->rate(), app_rate);#endif                if (app_rate > initial_window()) {			qs_cwnd_ = app_rate;                        qs_approved_ = 1;                }        } else { // Quick Start rejected#ifdef QS_DEBUG                printf("Quick Start rejected\n");#endif        }}/* * ACK has been received, hook from recv() */void TcpAgent::recv_frto_helper(Packet *pkt){	hdr_tcp *tcph = hdr_tcp::access(pkt);	if (tcph->seqno() == last_ack_ && frto_ != 0) {		/*		 * Duplicate ACK while in F-RTO indicates that the		 * timeout was valid. Go to slow start retransmissions.		 */		t_seqno_ = highest_ack_ + 1;		cwnd_ = frto_;		frto_ = 0;		// Must zero dupacks (in order to trigger send_much at recv)		// dupacks is increased in recv after exiting this function		dupacks_ = -1;	}}/* * A spurious timeout has been detected. Do appropriate actions. */void TcpAgent::spurious_timeout(){	frto_ = 0;	switch (spurious_response_) {	case 1:	default:		/*		 * Full revert of congestion window		 * (FlightSize before last acknowledgment)		 */		cwnd_ = t_seqno_ - prev_highest_ack_;		break; 	case 2:		/*		 * cwnd = reduced ssthresh (approx. half of the earlier pipe)		 */		cwnd_ = ssthresh_; break;	case 3:		/*		 * slow start, but without retransmissions		 */		cwnd_ = 1; break;	}	/*	 * Revert ssthresh to size before retransmission timeout	 */	ssthresh_ = pipe_prev_;	/* If timeout was spurious, bugfix is not needed */	recover_ = highest_ack_ - 1;}/* * Loss occurred in Quick-Start window. * If Quick-Start is enabled, packet loss in the QS phase should * trigger slow start instead of the regular fast retransmit, * see [draft-amit-quick-start-03.txt] (to appear). * We use variable tcp_qs_recovery_ to toggle this behaviour on and off. * If tcp_qs_recovery_ is true, initiate slow start to probe for * a correct window size. * * Return value: non-zero if Quick-Start specific loss recovery took place */int TcpAgent::lossQuickStart(){       if (qs_window_ && tcp_qs_recovery_) {                //recover_ = maxseq_;                //reset_rtx_timer(1,0);                slowdown(CLOSE_CWND_INIT);		// reset ssthresh to half of W-D/2?                qs_window_ = 0;                output(last_ack_ + 1, TCP_REASON_DUPACK);                return 1;       }       return 0;}/* * main reception path - should only see acks, otherwise the * network connections are misconfigured */void TcpAgent::recv(Packet *pkt, Handler*){	hdr_tcp *tcph = hdr_tcp::access(pkt);	int valid_ack = 0;	if (qs_approved_ == 1 && tcph->seqno() > last_ack_) 		endQuickStart();	if (qs_requested_ == 1)		processQuickStart(pkt);#ifdef notdef	if (pkt->type_ != PT_ACK) {		Tcl::instance().evalf("%s error \"received non-ack\"",				      name());		Packet::free(pkt);		return;	}#endif	/* W.N.: check if this is from a previous incarnation */	if (tcph->ts() < lastreset_) {		// Remove packet and do nothing		Packet::free(pkt);		return;	}	++nackpack_;	ts_peer_ = tcph->ts();	int ecnecho = hdr_flags::access(pkt)->ecnecho();	if (ecnecho && ecn_)		ecn(tcph->seqno());	recv_helper(pkt);	recv_frto_helper(pkt);	/* grow cwnd and check if the connection is done */ 	if (tcph->seqno() > last_ack_) {		recv_newack_helper(pkt);		if (last_ack_ == 0 && delay_growth_) { 			cwnd_ = initial_window();		}	} else if (tcph->seqno() == last_ack_) {                if (hdr_flags::access(pkt)->eln_ && eln_) {                        tcp_eln(pkt);                        return;                }		if (++dupacks_ == numdupacks_ && !noFastRetrans_) {			dupack_action();		} else if (dupacks_ < numdupacks_ && singledup_ ) {			send_one();		}	}	if (QOption_ && EnblRTTCtr_)		process_qoption_after_ack (tcph->seqno());	if (tcph->seqno() >= last_ack_)  		// Check if ACK is valid.  Suggestion by Mark Allman. 		valid_ack = 1;	Packet::free(pkt);	/*	 * Try to send more data.	 */	if (valid_ack || aggressive_maxburst_)		send_much(0, 0, maxburst_);}/* * Process timeout events other than rtx timeout. Having this as a separate  * function allows derived classes to make alterations/enhancements (e.g., * response to new types of timeout events). */ void TcpAgent::timeout_nonrtx(int tno) {	if (tno == TCP_TIMER_DELSND)  {	 /*	 	* delayed-send timer, with random overhead	 	* to avoid phase effects	 	*/		send_much(1, TCP_REASON_TIMEOUT, maxburst_);	}}	void TcpAgent::timeout(int tno){	/* retransmit timer */	if (tno == TCP_TIMER_RTX) {		// There has been a timeout - will trace this event		trace_event("TIMEOUT");		frto_ = 0;		// Set pipe_prev as per Eifel Response		pipe_prev_ = (window() > ssthresh_) ?			window() : (int)ssthresh_;	        if (cwnd_ < 1) cwnd_ = 1;		if (qs_approved_ == 1) qs_approved_ = 0;		if (highest_ack_ == maxseq_ && !slow_start_restart_) {			/*			 * TCP option:			 * If no outstanding data, then don't do anything.  			 */			 // Should this return be here?			 // What if CWND_ACTION_ECN and cwnd < 1?			 // return;		} else {			recover_ = maxseq_;			if (highest_ack_ == -1 && wnd_init_option_ == 2)				/* 				 * First packet dropped, so don't use larger				 * initial windows. 				 */				wnd_init_option_ = 1;			if (highest_ack_ == maxseq_ && restart_bugfix_)			       /* 				* if there is no outstanding data, don't cut 				* down ssthresh_.				*/				slowdown(CLOSE_CWND_ONE|NO_OUTSTANDING_DATA);			else if (highest_ack_ < recover_ &&			  last_cwnd_action_ == CWND_ACTION_ECN) {			       /*				* if we are in recovery from a recent ECN,				* don't cut down ssthresh_.				*/				slowdown(CLOSE_CWND_ONE);				if (frto_enabled_ || sfrto_enabled_) {					frto_ = 1;				}			}			else {				++nrexmit_;				last_cwnd_action_ = CWND_ACTION_TIMEOUT;				slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_RESTART);				if (frto_enabled_ || sfrto_enabled_) {					frto_ = 1;				}			}		}		/* if there is no outstanding data, don't back off rtx timer */		if (highest_ack_ == maxseq_ && restart_bugfix_) {			reset_rtx_timer(0,0);		}		else {			reset_rtx_timer(0,1);		}		last_cwnd_action_ = CWND_ACTION_TIMEOUT;		send_much(0, TCP_REASON_TIMEOUT, maxburst_);	} 	else {		timeout_nonrtx(tno);	}}/*  * Check if the packet (ack) has the ELN bit set, and if it does, and if the * last ELN-rxmitted packet is smaller than this one, then retransmit the * packet.  Do not adjust the cwnd when this happens. */void TcpAgent::tcp_eln(Packet *pkt){        //int eln_rxmit;        hdr_tcp *tcph = hdr_tcp::access(pkt);        int ack = tcph->seqno();        if (++dupacks_ == eln_rxmit_thresh_ && ack > eln_last_rxmit_) {                /* Retransmit this packet */                output(last_ack_ + 1, TCP_REASON_DUPACK);                eln_last_rxmit_ = last_ack_+1;        } else                send_much(0, 0, maxburst_);        Packet::free(pkt);        return;}/* * This function is invoked when the connection is done. It in turn * invokes the Tcl finish procedure that was registered with TCP. */void TcpAgent::finish(){	Tcl::instance().evalf("%s done", this->name());}void RtxTimer::expire(Event*){	a_->timeout(TCP_TIMER_RTX);}void DelSndTimer::expire(Event*){	a_->timeout(TCP_TIMER_DELSND);}void BurstSndTimer::expire(Event*){	a_->timeout(TCP_TIMER_BURSTSND);}/* * THE FOLLOWING FUNCTIONS ARE OBSOLETE, but REMAIN HERE * DUE TO OTHER PEOPLE's TCPs THAT MIGHT USE THEM * * These functions are now replaced by ecn() and slowdown(), * respectively. *//* * 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. */void TcpAgent::quench(int how){	if (highest_ack_ >= recover_) {		recover_ =  maxseq_;		last_cwnd_action_ = CWND_ACTION_ECN;		closecwnd(how);	}}/* * close down the congestion window */void TcpAgent::closecwnd(int how){   	static int first_time = 1;	if (first_time == 1) {		fprintf(stderr, "the TcpAgent::closecwnd() function is now deprecated, please use the function slowdown() instead\n");	}	switch (how) {	case 0:		/* timeouts */		ssthresh_ = int( window() / 2 );		if (ssthresh_ < 2 && increase_num_ >= 1.0)      // ktnahm mod			ssthresh_ = 2;		if (ssthresh_ < 0)      // ktnahm add			ssthresh_ = 0;  // ktnahm		cwnd_ = int(wnd_restart_);		break;	case 1:		/* Reno dup acks, or after a recent congestion indication. */		// cwnd_ = window()/2;		cwnd_ = decrease_num_ * window();		ssthresh_ = int(cwnd_);		if (ssthresh_ < 2 && increase_num_ >= 1.0)      // ktnahm mod			ssthresh_ = 2;		if (ssthresh_ < 0)      // ktnahm add			ssthresh_ = 0;  // ktnahm		break;	case 2:		/* Tahoe dup acks  				 * after a recent congestion indication */		cwnd_ = wnd_init_;		break;	case 3:		/* Retransmit timeout, but no outstanding data. */ 		cwnd_ = int(wnd_init_);		break;	case 4:		/* Tahoe dup acks */		ssthresh_ = int( window() / 2 );		if (ssthresh_ < 2 && increase_num_ >= 1.0)      // ktnahm mod			ssthresh_ = 2;		if (ssthresh_ < 0)      // ktnahm add			ssthresh_ = 0;  // ktnahm		cwnd_ = 1;		break;	default:		abort();	}	fcnt_ = 0.;	count_ = 0;}/* * Check if the sender has been idle or application-limited for more * than an RTO, and if so, reduce the congestion window. */void TcpAgent::process_qoption_after_send (){	int tcp_now = (int)(Scheduler::instance().clock()/tcp_tick_ + 0.5);	int rto = (int)(t_rtxcur_/tcp_tick_) ; 	/*double ct = Scheduler::instance().clock();*/	if (!EnblRTTCtr_) {		if (tcp_now - T_last >= rto) {			// The sender has been idle.		 	slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE) ;			for (int i = 0 ; i < (tcp_now - T_last)/rto; i ++) {				slowdown(CWND_HALF_WITH_MIN|TCP_IDLE);			}			T_prev = tcp_now ;			W_used = 0 ;		}		T_last = tcp_now ;		if (t_seqno_ == highest_ack_+ window()) {			T_prev = tcp_now ; 			W_used = 0 ; 		}		else if (t_seqno_ == curseq_-1) {			// The sender has no more data to send.			int tmp = t_seqno_ - highest_ack_ ;			if (tmp > W_used)				W_used = tmp ;			if (tcp_now - T_prev >= rto) {				// The sender has been application-limited.				slowdown(THREE_QUARTER_SSTHRESH|TCP_IDLE);				slowdown(CLOSE_CWND_HALF_WAY|TCP_IDLE);				T_prev = tcp_now ;				W_used 

⌨️ 快捷键说明

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