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

📄 red.cpp

📁 我自己写的 RED改进算法的代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	int victim;	if (drop_front_)		victim = min(1, q_->length()-1);	else if (drop_rand_)		victim = Random::integer(q_->length());	else			/* default is drop_tail_ */		victim = q_->length() - 1;	return(q_->lookup(victim)); }/* * Receive a new packet arriving at the queue. * The average queue size is computed.  If the average size * exceeds the threshold, then the dropping probability is computed, * and the newly-arriving packet is dropped with that probability. * The packet is also dropped if the maximum queue size is exceeded. * * "Forced" drops mean a packet arrived when the underlying queue was * full or when the average q size exceeded maxthresh. * "Unforced" means a RED random drop. * * For forced drops, either the arriving packet is dropped or one in the * queue is dropped, depending on the setting of drop_tail_. * For unforced drops, the arriving packet is always the victim. */#define	DTYPE_NONE	0	/* ok, no drop */#define	DTYPE_FORCED	1	/* a "forced" drop */#define	DTYPE_UNFORCED	2	/* an "unforced" (random) drop */void REDQueue::enque(Packet* pkt){	/*	 * if we were idle, we pretend that m packets arrived during	 * the idle period.  m is set to be the ptc times the amount	 * of time we've been idle for	 */	int m = 0;	if (idle_) {				//add 		//初始化令牌桶		tokens_=bucket_;		lastupdatetime_ = Scheduler::instance().clock();		//add over 						// A packet that arrives to an idle queue will never		//  be dropped.		double now = Scheduler::instance().clock();		/* To account for the period when the queue was empty. */		idle_ = 0;		m = int(edp_.ptc * (now - idletime_));	}	/*	 * Run the estimator with either 1 new packet arrival, or with	 * the scaled version above [scaled by m due to idle time]	 * (bcount_ maintains the byte count in the underlying queue).	 * If the underlying queue is able to delete packets without	 * us knowing, then bcount_ will not be maintained properly!	 */	edv_.v_ave = estimator(qib_ ? bcount_ : q_->length(), m + 1, edv_.v_ave, edp_.q_w);	//printf("v_ave: %6.4f (%13.12f) q: %d)\n", 	//	double(edv_.v_ave), double(edv_.v_ave), q_->length());	//run_estimator(qib_ ? bcount_ : q_->length(), m + 1);	/*	 * count and count_bytes keeps a tally of arriving traffic	 * that has not been dropped (i.e. how long, in terms of traffic,	 * it has been since the last early drop)	 */	hdr_cmn* ch = hdr_cmn::access(pkt);				//进行令牌计数		double tok;	  tok = getupdatedtokens();		int pktsize = ch->size();	if (tokens_ >=pktsize)		 {		 cou_grn ++;	    } 	else 		  {		   cou_red	++;	      };   if (cou_red = 0)      	{      		para_modi = 0 ;      		reset_cou();      	}   else       		{ if (cou_grn=1)      			{      				para_modi = 1- 1/cou_red;      				reset_cou();      			}      		}					//计数结束	++edv_.count;	edv_.count_bytes += ch->size();	/*	 * DROP LOGIC:	 *	q = current q size, ~q = averaged q size	 *	1> if ~q > maxthresh, this is a FORCED drop	 *	2> if minthresh < ~q < maxthresh, this may be an UNFORCED drop	 *	3> if (q+1) > hard q limit, this is a FORCED drop	 */	register double qavg = edv_.v_ave;	int droptype = DTYPE_NONE;	int qlen = qib_ ? bcount_ : q_->length();	int qlim = qib_ ? (qlim_ * edp_.mean_pktsize) : qlim_;	curq_ = qlen;	// helps to trace queue during arrival, if enabled	if (qavg >= edp_.th_min && qlen > 1) {		if ((!edp_.gentle && qavg >= edp_.th_max) ||			(edp_.gentle && qavg >= 2 * edp_.th_max)) {			droptype = DTYPE_FORCED;		} else if (edv_.old == 0) {			/* 			 * The average queue size has just crossed the			 * threshold from below to above "minthresh", or			 * from above "minthresh" with an empty queue to			 * above "minthresh" with a nonempty queue.			 */			edv_.count = 1;			edv_.count_bytes = ch->size();			edv_.old = 1;		} else if (drop_early(pkt)) {			droptype = DTYPE_UNFORCED;		}	} else {		/* No packets are being dropped.  */		edv_.v_prob = 0.0;		edv_.old = 0;			}	if (qlen >= qlim) {		// see if we've exceeded the queue size		droptype = DTYPE_FORCED;	}	if (droptype == DTYPE_UNFORCED) {		/* pick packet for ECN, which is dropping in this case */		Packet *pkt_to_drop = pickPacketForECN(pkt);		/* 		 * If the packet picked is different that the one that just arrived,		 * add it to the queue and remove the chosen packet.		 */		if (pkt_to_drop != pkt) {			q_->enque(pkt);			bcount_ += ch->size();			q_->remove(pkt_to_drop);			bcount_ -= hdr_cmn::access(pkt_to_drop)->size();			pkt = pkt_to_drop; /* XXX okay because pkt is not needed anymore */		}		// deliver to special "edrop" target, if defined		if (de_drop_ != NULL) {			//trace first if asked 		// if no snoop object (de_drop_) is defined, 		// this packet will not be traced as a special case.			if (EDTrace != NULL) 				((Trace *)EDTrace)->recvOnly(pkt);			reportDrop(pkt);			de_drop_->recv(pkt);		}		else {			reportDrop(pkt);			drop(pkt);		}	} else {		/* forced drop, or not a drop: first enqueue pkt */		q_->enque(pkt);		bcount_ += ch->size();		/* drop a packet if we were told to */		if (droptype == DTYPE_FORCED) {			/* drop random victim or last one */			pkt = pickPacketToDrop();			q_->remove(pkt);			bcount_ -= hdr_cmn::access(pkt)->size();			reportDrop(pkt);			drop(pkt);			if (!ns1_compat_) {				// bug-fix from Philip Liu, <phill@ece.ubc.ca>				edv_.count = 0;				edv_.count_bytes = 0;			}		}	}	return;}int REDQueue::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 2) {		if (strcmp(argv[1], "reset") == 0) {			reset();			return (TCL_OK);		}		if (strcmp(argv[1], "early-drop-target") == 0) {			if (de_drop_ != NULL)				tcl.resultf("%s", de_drop_->name());			return (TCL_OK);		}		if (strcmp(argv[1], "edrop-trace") == 0) {			if (EDTrace != NULL) {				tcl.resultf("%s", EDTrace->name());				if (debug_) 					printf("edrop trace exists according to RED\n");			}			else {				if (debug_)					printf("edrop trace doesn't exist according to RED\n");				tcl.resultf("0");			}			return (TCL_OK);		}		if (strcmp(argv[1], "trace-type") == 0) {			tcl.resultf("%s", traceType);			return (TCL_OK);		}	} 	else if (argc == 3) {		// attach a file for variable tracing		if (strcmp(argv[1], "attach") == 0) {			int mode;			const char* id = argv[2];			tchan_ = Tcl_GetChannel(tcl.interp(), (char*)id, &mode);			if (tchan_ == 0) {				tcl.resultf("RED: trace: can't attach %s for writing", id);				return (TCL_ERROR);			}			return (TCL_OK);		}		// tell RED about link stats		if (strcmp(argv[1], "link") == 0) {			LinkDelay* del = (LinkDelay*)TclObject::lookup(argv[2]);			if (del == 0) {				tcl.resultf("RED: no LinkDelay object %s",					argv[2]);				return(TCL_ERROR);			}			// set ptc now			link_ = del;			edp_.ptc = link_->bandwidth() /				(8. * edp_.mean_pktsize);			return (TCL_OK);		}		if (strcmp(argv[1], "early-drop-target") == 0) {			NsObject* p = (NsObject*)TclObject::lookup(argv[2]);			if (p == 0) {				tcl.resultf("no object %s", argv[2]);				return (TCL_ERROR);			}			de_drop_ = p;			return (TCL_OK);		}		if (strcmp(argv[1], "edrop-trace") == 0) {			if (debug_) 				printf("Ok, Here\n");			NsObject * t  = (NsObject *)TclObject::lookup(argv[2]);			if (debug_)  				printf("Ok, Here too\n");			if (t == 0) {				tcl.resultf("no object %s", argv[2]);				return (TCL_ERROR);			}			EDTrace = t;			if (debug_)  				printf("Ok, Here too too too %d\n", ((Trace *)EDTrace)->type_);			return (TCL_OK);		}		if (!strcmp(argv[1], "packetqueue-attach")) {			delete q_;			if (!(q_ = (PacketQueue*) TclObject::lookup(argv[2])))				return (TCL_ERROR);			else {				pq_ = q_;				return (TCL_OK);			}		}	}	return (Queue::command(argc, argv));}/* * Routine called by TracedVar facility when variables change values. * Currently used to trace values of avg queue size, drop probability, * and the instantaneous queue size seen by arriving packets. * Note that the tracing of each var must be enabled in tcl to work. */voidREDQueue::trace(TracedVar* v){	char wrk[500], *p;	if (((p = strstr(v->name(), "ave")) == NULL) &&	    ((p = strstr(v->name(), "prob")) == NULL) &&	    ((p = strstr(v->name(), "curq")) == NULL)) {		fprintf(stderr, "RED:unknown trace var %s\n",			v->name());		return;	}	if (tchan_) {		int n;		double t = Scheduler::instance().clock();		// XXX: be compatible with nsv1 RED trace entries		if (*p == 'c') {			sprintf(wrk, "Q %g %d", t, int(*((TracedInt*) v)));		} else {			sprintf(wrk, "%c %g %g", *p, t,				double(*((TracedDouble*) v)));		}		n = strlen(wrk);		wrk[n] = '\n'; 		wrk[n+1] = 0;		(void)Tcl_Write(tchan_, wrk, n+1);	}	return; }/* for debugging help */void REDQueue::print_edp(){	printf("mean_pktsz: %d\n", edp_.mean_pktsize); 	printf("bytes: %d, wait: %d, setbit: %d\n",	       edp_.bytes, edp_.wait, edp_.setbit);	printf("minth: %f, maxth: %f\n", edp_.th_min, edp_.th_max);	printf("max_p_inv: %f, qw: %f, ptc: %f\n",	       edp_.max_p_inv, edp_.q_w, edp_.ptc);	printf("qlim: %d, idletime: %f\n", qlim_, idletime_);	printf("=========\n");}void REDQueue::print_edv(){	printf("v_a: %f, v_b: %f\n", edv_.v_a, edv_.v_b);}/************************************************************//* * This procedure is obsolete, and only included for backward compatibility. * The new procedure is REDQueue::estimator */ /* * Compute the average queue size. * The code contains two alternate methods for this, the plain EWMA * and the Holt-Winters method. * nqueued can be bytes or packets */void REDQueue::run_estimator(int nqueued, int m){	double f, f_sl, f_old;	f = edv_.v_ave;	f_sl = edv_.v_slope;#define RED_EWMA#ifdef RED_EWMA	while (--m >= 1) {		f_old = f;		f *= 1.0 - edp_.q_w;	}	f_old = f;	f *= 1.0 - edp_.q_w;	f += edp_.q_w * nqueued;#endif#ifdef RED_HOLT_WINTERS	while (--m >= 1) {		f_old = f;		f += f_sl;		f *= 1.0 - edp_.q_w;		f_sl *= 1.0 - 0.5 * edp_.q_w;		f_sl += 0.5 * edp_.q_w * (f - f_old);	}	f_old = f;	f += f_sl;	f *= 1.0 - edp_.q_w;	f += edp_.q_w * nqueued;	f_sl *= 1.0 - 0.5 * edp_.q_w;	f_sl += 0.5 * edp_.q_w * (f - f_old);#endif	edv_.v_ave = f;	edv_.v_slope = f_sl;}

⌨️ 快捷键说明

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