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

📄 tcp-westwood-nr.cc

📁 NS2 simulation TCP westwood
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1990, 2001 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Lawrence Berkeley Laboratory, * Berkeley, CA.  The name of the University may not be used to * endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintstatic const char rcsid[] =    "@(#) $Header: /mvalla/tcp-w-nr.cc,v 1.2 2001/09/17 15:12:29 mvalla Exp mvalla $ (LBL)";#endif//// tcp-w-nr: a revised New Reno TCP source, with faster recovery//#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <math.h>#include "packet.h"#include "ip.h"#include "tcp.h"#include "flags.h"#include "address.h"#include "tcp-westwood-nr.h"static class WestwoodNRTcpClass : public TclClass {public:	WestwoodNRTcpClass() : TclClass("Agent/TCP/WestwoodNR") {}	TclObject* create(int, const char*const*) {		return (new WestwoodNRTcpAgent());	}} class_westwoodnr;///// // WestwoodNRTcpAgent()WestwoodNRTcpAgent::WestwoodNRTcpAgent() : NewRenoTcpAgent(),  // these where originally in TcpAgent()  current_bwe_(0), last_bwe_sample_(0), unaccounted_(0),  fr_a_(0), min_rtt_estimate(5.0), myseqno_(1),last_ts_(0),last_echoed_ts_(0),last_seq_(0),  lastackrx_(0.0), fr_alpha_(0.9), filter_type_(1), tau_(1.0), total_time_(0.0), total_size_(0.0), fr_prev_(20.0){	// Read defaults variables from ns-defaults.tcl	// these where originally in TcpAgent()		bind("current_bwe_", &current_bwe_);	bind("last_bwe_sample_", &last_bwe_sample_);  	bind("unaccounted_", &unaccounted_);  	bind("fr_a_", &fr_a_);	bind("fr_amin_", &fr_amin_);	bind("fr_amax_", &fr_amax_);	bind("fr_prev_", &fr_prev_);  	bind("min_rtt_estimate", &min_rtt_estimate);	bind("fr_alpha_", &fr_alpha_);	bind("filter_type_", &filter_type_);	bind("tau_", &tau_);	bind("west_type_",&west_type_);	bind("qest_",&qest_);	bind("total_time_",&total_time_);	bind("total_size_",&total_size_);	bind("interp_type_",&interp_type_);	bind("last_ts_",&last_ts_);	bind("last_echoed_ts_",&last_echoed_ts_);	bind("last_seq_",&last_seq_);	bind("last_cwnd_",&last_cwnd_);	bind("current_ts_",&current_ts_);	bind("current_echoed_ts_",&current_echoed_ts_);	// these where originally in NewRenoTcpAgent()	bind("newreno_changes_", &newreno_changes_);	bind("newreno_changes1_", &newreno_changes1_);	bind("exit_recovery_fix_", &exit_recovery_fix_);	bind("partial_window_deflation_", &partial_window_deflation_);	bind("openadd_", &openadd_);	//printf("Westwood New Reno binding done!\n");}///// // dupack_action()void WestwoodNRTcpAgent::dupack_action(){	int recovered = (highest_ack_ > recover_);        int allowFastRetransmit = allow_fast_retransmit(last_cwnd_action_);        if (recovered || (!bug_fix_ && !ecn_) || allowFastRetransmit) {                goto reno_action;        }        if (ecn_ && last_cwnd_action_ == CWND_ACTION_ECN) {                last_cwnd_action_ = CWND_ACTION_DUPACK;                /*                 * What if there is a DUPACK action followed closely by ECN                 * followed closely by a DUPACK action?                 * The optimal thing to do would be to remember all                 * congestion actions from the most recent window                 * of data.  Otherwise "bugfix" might not prevent                 * all unnecessary Fast Retransmits.                 */                reset_rtx_timer(1,0);                output(last_ack_ + 1, TCP_REASON_DUPACK);                return;        }        if (bug_fix_) {                /*                 * The line below, for "bug_fix_" true, avoids                 * problems with multiple fast retransmits in one                 * window of data.                 */                return;        }reno_action:/*         if (ssthresh_ > cwnd_) {	fr_a_+=0.25;	if (fr_a_ > 4)	  fr_a_=4;      } else {	fr_a_ = 1;      }  	ssthresh_ = (int)((current_bwe_/size_/8) * min_rtt_estimate);      	if (cwnd_ > ssthresh_) {      		cwnd_ = ssthresh_;      	}	*/double fr_now = Scheduler::instance().clock();double rtt_estimate = t_rtt_ * tcp_tick_;if ((rtt_estimate < min_rtt_estimate)&&(rtt_estimate > 0)) {		   min_rtt_estimate = rtt_estimate;		}/* west_type_ = 3 west+   *///if (west_type_<=4)fr_a_=-1;double sstemp=(((current_bwe_*(min_rtt_estimate))/((double)(size_*8.0))));if (sstemp < 2) sstemp = 2;//if (sstemp1 < 2) sstemp1 = 2;		ssthresh_ = (int)(sstemp);		if (cwnd_ > sstemp) {cwnd_ = sstemp;}	trace_event("TCPWNR_FAST_RETX");        recover_ = maxseq_;        last_cwnd_action_ = CWND_ACTION_DUPACK;        // The slowdown was already performed        // slowdown(CLOSE_SSTHRESH_HALF|CLOSE_CWND_HALF);        reset_rtx_timer(1,0);        output(last_ack_ + 1, TCP_REASON_DUPACK);        return;}/////// timeout()void WestwoodNRTcpAgent::timeout(int tno){	/* retransmit timer */	if (tno == TCP_TIMER_RTX) {		if (highest_ack_ == maxseq_ && !slow_start_restart_) {			/*			 * TCP option:			 * If no outstanding data, then don't do anything.			 */			return;		};		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);		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);		}		else {			++nrexmit_;			slowdown(CLOSE_FASTER);		}		/* 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);	}}///// // bwe_computation()void WestwoodNRTcpAgent::bwe_computation(Packet *pkt) {		hdr_tcp *tcph = hdr_tcp::access(pkt);	double fr_now = Scheduler::instance().clock();	hdr_flags *fh = hdr_flags::access(pkt);		// last_ack_ indicates the ack no. of the ack received _before_	// the current one 		// START BWE COMPUTATION  // Idea: cumulative ACKs acking more than 2 packets count for 1 packet	//   since DUPACKs have already been accounted for	int cumul_ack = tcph->seqno_ - last_ack_;	int cumul_ack1 = cumul_ack; //used for queueing time estimation	myseqno_ = tcph->seqno_;	if (cumul_ack > 1) {	  /* check if current ACK ACKs fewer or same number of segments than */	  /* expected: if so, the missing ones were already accounted for by */	  /* DUPACKs, and current ACK only counts as 1 */	  if (unaccounted_ >= cumul_ack) {	    unaccounted_-=cumul_ack;	    cumul_ack=1;	  } else	  /* check if current ACK ACKs more segments than expected: if so,   */	  /* part of them were already accounted for by DUPACKs; the rest    */	  /* are cumulatively ACKed by present ACK. Make present ACK count   */	  /* as the unacknowledged ACKs in excess*/	  if (unaccounted_ < cumul_ack) {	    cumul_ack-=unaccounted_;	    unaccounted_=0;	  }	}  /* if cumul_ack=0, the current ACK is clearly a DUPACK and should */	/* count 1 */	if (cumul_ack == 0) {	  unaccounted_++;	  cumul_ack=1;	}  /* safety check; if the previous steps are followed exactly,      */	/* cumul_ack should not be >2 unless some strage events occur     */	/* (e.g., an ACK is dropped on the way back and the following one */	/* appears to ACK more than its due)                              */	if (cumul_ack > 2) {	  cumul_ack=2;	  }	nackpack_+= cumul_ack;	last_seq_+=cumul_ack;	//qest_=cwnd_-(current_bwe_*min_rtt_estimate)/(8.0*(double)size_);	current_ts_=tcph->ts();	current_echoed_ts_=tcph->ts_echo();	double rtt_estimate = t_rtt_ * tcp_tick_;			  if ((rtt_estimate < min_rtt_estimate)&&(rtt_estimate > 0)) {		  min_rtt_estimate = rtt_estimate;		qest_=0; 		last_echoed_ts_=current_echoed_ts_; 		last_ts_=current_ts_;		}		qest_=qest_+(current_ts_-last_ts_)-(current_echoed_ts_-last_echoed_ts_);		last_echoed_ts_=current_echoed_ts_; 		last_ts_=current_ts_;//if (west_type_==5) qest_=cwnd_-(current_bwe_*min_rtt_estimate)/(8.0*(double)size_);	int acked_size = size_ * 8 * cumul_ack;	double ack_interv = fr_now - lastackrx_;	double sample_bwe;	double last_tmp_bwe;	int idle_intervals;	switch (filter_type_) {	  case 0:          //   original filter	  sample_bwe = acked_size/ack_interv;	  current_bwe_ = current_bwe_ * fr_alpha_ + sample_bwe * (1 - fr_alpha_);	  last_bwe_sample_ = sample_bwe;	  break;	  case 1:	  // filter type 1	  sample_bwe = acked_size/ack_interv;	  current_bwe_ = current_bwe_ * .9047 +	               (sample_bwe + last_bwe_sample_) * .0476;	last_bwe_sample_ = sample_bwe;	  break;		  case 2:	  // filter type 2: 'lower' pass	  sample_bwe = acked_size/ack_interv;	  current_bwe_ = current_bwe_ * .93548 + 	               (sample_bwe+last_bwe_sample_) * .03225;	  last_bwe_sample_ = sample_bwe;	  break;	  case 3:	  // filter type 3: time constant tau_	  // compute how many intervals of length tau_/2 went by since we	  // received the last ACK. For each tau_/2 interval without ACK, feed          // a zero-bandwidth sample to the filter.	  idle_intervals = (int)(ack_interv / tau_*2.0);	  //	  printf("idle_intervals = %d (%f,%f)=%f\n", idle_intervals, ack_interv, tau_,	  //				ack_interv / tau_);	  //		printf("idle_intervals = %d, ratio= %f\n",idle_intervals, ack_interv / tau_);	  	  ack_interv -= tau_ /2.0 * idle_intervals;	  	  //if ( (ack_interv < 0.01) && (idle_intervals == 0) ){	  //	printf("TCP-W error: (ack_interv < 0.01) && (idle_intervals == 0)\n");	  //	printf("time=%lf, last_ack=%lf, ack_interv=%lf\n", fr_now, lastackrx_, ack_interv);	  //	//exit(0);	  //}		  	  if ( (ack_interv < 0.01) && (idle_intervals > 0) ) {	  // ack_interv was a multiple of tau_/2 or the remainder is too small (less than 10ms), so 	  // we consider tau_ / 2 as the last interval	  	ack_interv = tau_ / 2.0;		idle_intervals -= 1; // we do not count the last tau_/2 interval	  }	  	  sample_bwe = acked_size/ack_interv;	  	  if (idle_intervals > 0) { // feed the filter	  	// printf("idle_intervals = %d\n", idle_intervals);		for (int i=0; i<idle_intervals; i++) {			current_bwe_ = current_bwe_ * 3.0 / 5.0  + last_bwe_sample_/5.0;			last_bwe_sample_ = 0.0;			//  printf("idle_interval: current_bwe=%f\n", current_bwe_);		}	  }	  	  last_tmp_bwe = current_bwe_; // we need it just for the printf...	  current_bwe_ = current_bwe_ * (2.0*tau_-ack_interv) /		           (2.0*tau_+ack_interv) +		           ack_interv*(sample_bwe + last_bwe_sample_)/(2.0*tau_+ack_interv);	last_bwe_sample_ = sample_bwe;	  if (current_bwe_ < 0) {			printf("TCP-W error: current_bwe_ < 0\n");			printf("time: %f, last_tmp_bwe=%f\n", fr_now, last_tmp_bwe);			printf("current_bwe_%f, ack_interv=%f, sample_bwe=%f, last_bwe_sample_=%f\n",					current_bwe_, ack_interv, sample_bwe, last_bwe_sample_);			exit(0);	  }	  break;	  case 4:	total_size_ = total_size_ + acked_size;	total_time_ = total_time_ + ack_interv;	if (((rtt_estimate >0)&&(total_time_>rtt_estimate))) {        sample_bwe = total_size_/total_time_;	double m=(sample_bwe-last_bwe_sample_)/pow(total_time_,interp_type_);

⌨️ 快捷键说明

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