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

📄 zhinengpid.cc

📁 将智能PID用VC++实现
💻 CC
字号:
/* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 1990-1997 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the Computer Systems *	Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used *    to endorse or promote products derived from this software without *    specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * *//* * Based on PI controller described in: * C. Hollot, V. Misra, D. Towsley and W. Gong.  * On Designing Improved Controllers for AQM Routers * Supporting TCP Flows,  * INFOCOMM 2001.  */#include <math.h>#include <sys/types.h>#include "config.h"#include "template.h"#include "random.h"#include "flags.h"#include "delay.h"#include "pi.h"static class PIClass : public TclClass {public:	PIClass() : TclClass("Queue/PI") {}	TclObject* create(int argc, const char*const* argv) {		if (argc==5) 			return (new PIQueue(argv[4]));		else			return (new PIQueue("Drop"));	}} class_pi;PIQueue::PIQueue(const char * trace) : CalcTimer(this), link_(NULL), q_(NULL),	qib_(0), de_drop_(NULL), EDTrace(NULL), tchan_(0), curq_(0),	edp_(), edv_(), first_reset_(1){	if (strlen(trace) >=20) {		printf("trace type too long - allocate more space to traceType in pi.h and recompile\n");		exit(0);	}	strcpy(traceType, trace);	bind_bool("bytes_", &edp_.bytes);	    // boolean: use bytes?	bind_bool("queue_in_bytes_", &qib_);	    // boolean: q in bytes?	bind("a_", &edp_.a);			bind("b_", &edp_.b);	bind("c_", &edp_.c);        bind("m1_", &edp_.m1);			bind("m2_", &edp_.m2);	bind("m_", &edp_.m);        bind("k1_", &edp_.k1);			bind("k2_", &edp_.k2);	bind("k3_", &edp_.k3);	bind("w_", &edp_.w);		  	bind("qref_", &edp_.qref);		  	bind("mean_pktsize_", &edp_.mean_pktsize);  // avg pkt size	bind_bool("setbit_", &edp_.setbit);	    // mark instead of drop	bind("prob_", &edv_.v_prob);		    // dropping probability	bind("curq_", &curq_);			    // current queue size	q_ = new PacketQueue();			    // underlying queue	pq_ = q_;	reset();}void PIQueue::reset(){	//double now = Scheduler::instance().clock();	/*	if (qib_ && first_reset_ == 1) {		edp_.qref = edp_.qref*edp_.mean_pktsize;	}	*/	edv_.count = 0;	edv_.count_bytes = 0;	edv_.v_prob = 0;	edv_.qold = 0;        edv_.qoldold = 0;        edv_.e = 0;        edv_.eold = 0;	curq_ = 0;	calculate_p();	Queue::reset();}void PIQueue::enque(Packet* pkt){	//double now = Scheduler::instance().clock();	hdr_cmn* ch = hdr_cmn::access(pkt);	++edv_.count;	edv_.count_bytes += ch->size();	int droptype = DTYPE_NONE;	int qlen = qib_ ? q_->byteLength() : q_->length();	curq_ = qlen;	// helps to trace queue during arrival, if enabled	int qlim = qib_ ? (qlim_ * edp_.mean_pktsize) : qlim_;	if (qlen >= qlim) {		droptype = DTYPE_FORCED;	}	else {		if (drop_early(pkt, qlen)) {			droptype = DTYPE_UNFORCED;		}	}	if (droptype == DTYPE_UNFORCED) {		Packet *pkt_to_drop = pickPacketForECN(pkt);		if (pkt_to_drop != pkt) {			q_->enque(pkt);			q_->remove(pkt_to_drop);			pkt = pkt_to_drop; /* XXX okay because pkt is not needed anymore */		}		if (de_drop_ != NULL) {			if (EDTrace != NULL) 				((Trace *)EDTrace)->recvOnly(pkt);			de_drop_->recv(pkt);		}		else {			drop(pkt);		}	} else {		q_->enque(pkt);		if (droptype == DTYPE_FORCED) {			pkt = pickPacketToDrop();			q_->remove(pkt);			drop(pkt);			edv_.count = 0;			edv_.count_bytes = 0;		}	}	return;}double PIQueue::calculate_p(){	//double now = Scheduler::instance().clock();	double p;	int qlen = qib_ ? q_->byteLength() : q_->length();		if (qib_) {                 edv_.e = qlen*1.0/edp_.mean_pktsize-edp_.qref;                 if (edv_.e > 0) edv_.e=edv_.e;                 else edv_.e=-edv_.e;                                   if (edv_.e > edp_.m1) {		        p=edp_.k3*(edp_.a*(qlen*1.0/edp_.mean_pktsize-edp_.qref)-			  edp_.b*(edv_.qold*1.0/edp_.mean_pktsize-edp_.qref)+                          edp_.c*(edv_.qoldold*1.0/edp_.mean_pktsize-edp_.qref))+			  edv_.v_prob; }                  else if (edv_.e < edp_.m) {                        p=(edp_.a+edp_.c-edp_.b)*(qlen*1.0/edp_.mean_pktsize-edp_.qref)+			  edv_.v_prob; }                  else if (edv_.e > edp_.m2) {                         if (edv_.e > edv_.eold) {                          p=edp_.k1*(edp_.a*(qlen*1.0/edp_.mean_pktsize-edp_.qref)-			  edp_.b*(edv_.qold*1.0/edp_.mean_pktsize-edp_.qref)+                          edp_.c*(edv_.qoldold*1.0/edp_.mean_pktsize-edp_.qref))+			  edv_.v_prob; }                  else p=edp_.k2*(edp_.a*(qlen*1.0/edp_.mean_pktsize-edp_.qref)-			  edp_.b*(edv_.qold*1.0/edp_.mean_pktsize-edp_.qref)+                          edp_.c*(edv_.qoldold*1.0/edp_.mean_pktsize-edp_.qref))+			  edv_.v_prob;  }                                                             else p=(edp_.a+edp_.c-edp_.b)*(qlen*1.0/edp_.mean_pktsize-edp_.qref)+			  edv_.v_prob;                                                                                                        }          		else {    edv_.e = qlen-edp_.qref;                 if (edv_.e > 0) edv_.e=edv_.e;                 else edv_.e=-edv_.e;                                   if (edv_.e > edp_.m1) {		        p=edp_.k3*(edp_.a*(qlen-edp_.qref)-edp_.b*(edv_.qold-edp_.qref)+                          edp_.c*(edv_.qoldold-edp_.qref))+edv_.v_prob; }                  else if (edv_.e < edp_.m) {                        p=(edp_.a+edp_.c-edp_.b)*(qlen-edp_.qref)+edv_.v_prob; }                  else if (edv_.e > edp_.m2) {                         if (edv_.e > edv_.eold) {                          p=edp_.k1*(edp_.a*(qlen-edp_.qref)-edp_.b*(edv_.qold-edp_.qref)+                          edp_.c*(edv_.qoldold-edp_.qref))+edv_.v_prob; }                  else p=edp_.k2*(edp_.a*(qlen-edp_.qref)-edp_.b*(edv_.qold-edp_.qref)+                          edp_.c*(edv_.qoldold-edp_.qref))+edv_.v_prob;                                           }                  else p=(edp_.a+edp_.c-edp_.b)*(qlen-edp_.qref)+edv_.v_prob;                                                                                                           }          				if (p < 0) p = 0;	if (p > 1) p = 1;		edv_.v_prob = p;	edv_.qold = qlen;        edv_.qoldold = edv_.qold;        edv_.eold = edv_.e;	CalcTimer.resched(1.0/edp_.w);	return p;}int PIQueue::drop_early(Packet* pkt, int qlen){	//double now = Scheduler::instance().clock();	hdr_cmn* ch = hdr_cmn::access(pkt);	double p = edv_.v_prob; 	if (edp_.bytes) {		p = p*ch->size()/edp_.mean_pktsize;		if (p > 1) p = 1; 	}	double u = Random::uniform();	if (u <= p) {		edv_.count = 0;		edv_.count_bytes = 0;		hdr_flags* hf = hdr_flags::access(pickPacketForECN(pkt));		if (edp_.setbit && hf->ect()) {			hf->ce() = 1; 	// mark Congestion Experienced bit			return (0);	// no drop		} else {			return (1);	// drop		}	}	return (0);			// no DROP/mark}Packet* PIQueue::pickPacketForECN(Packet* pkt){	return pkt; /* pick the packet that just arrived */}Packet* PIQueue::pickPacketToDrop() {	int victim;	victim = q_->length() - 1;	return(q_->lookup(victim)); }Packet* PIQueue::deque(){	Packet *p;	p = q_->deque();	curq_ = qib_ ? q_->byteLength() : q_->length(); // helps to trace queue during arrival, if enabled	return (p);}int PIQueue::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());			}			else {				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("PI: trace: can't attach %s for writing", id);				return (TCL_ERROR);			}			return (TCL_OK);		}		// tell PI about link stats		if (strcmp(argv[1], "link") == 0) {			LinkDelay* del = (LinkDelay*)TclObject::lookup(argv[2]);			if (del == 0) {				tcl.resultf("PI: no LinkDelay object %s", argv[2]);				return(TCL_ERROR);			}			link_ = del;			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) {			NsObject * t  = (NsObject *)TclObject::lookup(argv[2]);			if (t == 0) {				tcl.resultf("no object %s", argv[2]);				return (TCL_ERROR);			}			EDTrace = t;			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));}void PIQueue::trace(TracedVar* v){	char wrk[500], *p;	if (((p = strstr(v->name(), "prob")) == NULL) &&	    ((p = strstr(v->name(), "curq")) == NULL)) {		fprintf(stderr, "PI:unknown trace var %s\n", v->name());		return;	}	if (tchan_) {		int n;		double t = Scheduler::instance().clock();		// XXX: be compatible with nsv1 PI 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; }void PICalcTimer::expire(Event *){	a_->calculate_p();}

⌨️ 快捷键说明

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