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

📄 cbq.cc

📁 CBQ的源代码
💻 CC
📖 第 1 页 / 共 2 页
字号:
	 * Add to per-level list	 *	and store the highest level# we've seen	 */	if (p->level_ <= 0 || p->level_ > MAXLEVEL) {		fprintf(stderr, "CBQ class %s has invalid level %d\n",			p->name(), p->level_);		return (-1);	}	p->level_peer_ = levels_[p->level_];	levels_[p->level_] = p;	if (p->level_ > maxlevel_)		maxlevel_ = p->level_;	/*	 * Check that parent and borrow linkage are acyclic.	 */#ifdef notdef	check_for_cycles(CBQClass::parent);	check_for_cycles(CBQClass::borrow);#endif	return 0;}int CBQueue::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 3) {		if (strcmp(argv[1], "insert-class") == 0) {			CBQClass *cl = (CBQClass*)TclObject::lookup(argv[2]);			if (cl == 0) {				tcl.resultf("CBQ: no class object %s",					argv[2]);				return (TCL_ERROR);			}			if (insert_class(cl) < 0) {				tcl.resultf("CBQ: trouble inserting class %s",					argv[2]);				return (TCL_ERROR);			}			return (TCL_OK);		}		if (strcmp(argv[1], "link") == 0) {			LinkDelay* del = (LinkDelay*)TclObject::lookup(argv[2]);			if (del == 0) {				tcl.resultf("CBQ: no LinkDelay object %s",					argv[2]);				return(TCL_ERROR);			}			link_ = del;			return (TCL_OK);		}		if (strcmp(argv[1], "algorithm") == 0) {			if (algorithm(argv[2]) < 0)				return (TCL_ERROR);			return (TCL_OK);		}	}	return (Queue::command(argc, argv));}class WRR_CBQueue : public CBQueue {public:	WRR_CBQueue() {		memset(M_, '\0', sizeof(M_));		memset(alloc_, '\0', sizeof(alloc_));		memset(cnt_, '\0', sizeof(cnt_));	}	void	addallot(int prio, double diff) {		alloc_[prio] += diff;		setM();	}protected:	Packet *deque();	int	insert_class(CBQClass*);	void	setM();	double	alloc_[MAXPRIO];	double	M_[MAXPRIO];	int	cnt_[MAXPRIO];		// # classes at prio of index	int	command(int argc, const char*const* argv);};static class WRR_CBQQueueClass : public TclClass {public:	WRR_CBQQueueClass() : TclClass("Queue/CBQ/WRR") { }	TclObject* create(int, const char*const*) {		return (new WRR_CBQueue);	}} class_wrr_cbq;int WRR_CBQueue::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (strcmp(argv[1], "insert-class") == 0) {		CBQClass *cl = (CBQClass*)TclObject::lookup(argv[2]);		if (cl == 0) {			tcl.resultf("WRR-CBQ: no class object %s",				argv[2]);			return (TCL_ERROR);		}		if (insert_class(cl) < 0) {			tcl.resultf("WRR-CBQ: trouble inserting class %s",				argv[2]);			return (TCL_ERROR);		}		return (TCL_OK);	}	return (CBQueue::command(argc, argv));}Packet *WRR_CBQueue::deque(){	double now = Scheduler::instance().clock();	CBQClass* first = NULL;	CBQClass* eligible = NULL;	CBQClass* next_eligible = NULL;	CBQClass* cl;	register int prio;	int deficit, done;	int none_found = 0;	Packet* rval;	/*	 * prio runs from 0 .. maxprio_	 *	 * round-robin through all the classes at priority 'prio'	 *      if any class is ok to send, resume it's queue	 * go on to next lowest priority (higher prio nuber) and repeat	 * [lowest priority number is the highest priority]	 */	for (prio = 0; prio <= maxprio_; prio++) {		// see if there is any class at this prio		if ((cl = active_[prio]) == NULL) {			// nobody at this prio level			continue;		}                /*                  * The WRR round for this priority level starts at deficit 0.                 *  The round ends if some class is found that is ready                 *  to send and has positive "bytes_alloc_".                 * Status advances to deficit 1 if some class was found                   *  that was able to send except for insufficient                 *  "bytes_alloc_".                 * If status was deficit 1 at the end of the first round,                 *  then status advances to deficit 2.                 * Another round of WRR is then begun at deficit 2, looking                 *  for a class to send even with insufficient "bytes_alloc_".                 */		deficit = done = 0;		while (!done) {                        // look for class at this priority level ok to send			do {                                // set up "weight" for WRR				if (deficit < 2 && cl->bytes_alloc_ <= 0)					cl->bytes_alloc_ +=						(int)(cl->allotment_ * M_[cl->pri_]);                                // anything to send?				if (cl->demand()) {					if (first == NULL && cl->permit_borrowing_ && cl->lender_ != NULL)						first = cl;					if (!send_permitted(cl, now)) {                                                // not ok to send right now						cl->delayed(now);					} else {                                                // ok to send, if class has                                                //  enough "weight" for WRR.						int bytes = cl->bytes_alloc_;						if (bytes > 0 || deficit > 1) {							eligible = cl;							goto found;						} else							deficit = 1;					}				}				cl->bytes_alloc_ = 0;				cl = cl->peer_;			} while (cl != active_[prio] && cl != 0);			if (deficit == 1)				deficit = 2;			else				done = 1;		}	}        // did not find anyone so let first go	if ((eligible == NULL) && first != NULL) {		none_found = 1;		eligible = first;	}found:	// do accounting	if (eligible != NULL) {		next_eligible = eligible->peer_;		eligible->q_->resume();		if (pending_pkt_ != NULL && !none_found) {			// reduce our alloc			// by the packet size.  If we're			// still positive, we get to go again			int bytes = eligible->bytes_alloc_;			hdr_cmn* hdr = hdr_cmn::access(pending_pkt_);			if (bytes > 0) {				eligible->bytes_alloc_ -= hdr->size();			}			bytes = eligible->bytes_alloc_;			if (bytes > 0) {				next_eligible = eligible;			}			eligible->update(pending_pkt_, now);			if (toplevel())				toplevel_departure(eligible, now);		}		active_[eligible->pri_] = next_eligible;	}	rval = pending_pkt_;	pending_pkt_ = NULL;	return (rval);}intWRR_CBQueue::insert_class(CBQClass *p){	if (CBQueue::insert_class(p) < 0)		return (-1);	++cnt_[p->pri_];	setM();	return (0);}voidWRR_CBQueue::setM(){	int i;	for (i = 0; i <= maxprio_; i++) {		if (alloc_[i] > 0.0)                        // allocate "cnt_[i] * maxpkt_" bytes to each                        //  priority level:                        M_[i] = cnt_[i] * maxpkt_ * 1.0 / alloc_[i];                        // allocate "alloc_[i] * 2.0 * cnt_[i] * maxpkt_"                        //  bytes to each priority level:                        //  M_[i] = 2.0 * cnt_[i] * maxpkt_;		else			M_[i] = 0.0;		if (M_[i] < 0.0) {			fprintf(stderr, "M_[i]: %f, cnt_[i]: %d, maxpkt_: %d, alloc_[i]: %f\n",				M_[i], cnt_[i], maxpkt_, alloc_[i]);			abort();		}	}	return;}/******************** CBQClass definitions **********************/CBQClass::CBQClass() : cbq_(0), peer_(0), level_peer_(0), lender_(0),	q_(0), qmon_(0), allotment_(0.0), maxidle_(-1.0), maxrate_(0.0),	extradelay_(0.0), last_time_(0.0), undertime_(0.0), avgidle_(0.0),	pri_(-1), level_(-1), delayed_(0), bytes_alloc_(0),	permit_borrowing_(1){	/* maxidle_ is no longer bound; it is now a method interface */	bind("priority_", &pri_);	bind("level_", &level_);	bind("extradelay_", &extradelay_);	bind_bool("okborrow_", &permit_borrowing_);	if (pri_ < 0 || pri_ > (MAXPRIO-1))		abort();	if (level_ <= 0 || level_ > MAXLEVEL)		abort();}// why can't these two be inline (?)intCBQClass::demand(){	return (qmon_->pkts() > 0);}intCBQClass::leaf(){	return (level_ == LEAF_LEVEL);}/* * we are upstream from the queue * the queue should be unblocked if the downstream * cbq is not busy and blocked otherwise * * we get our packet from the classifier, because of * this the handler is NULL.  Besides the queue downstream * from us (Queue::recv) ignores the handler anyhow *  */voidCBQClass::recv(Packet *pkt, Handler *h){	if (cbq_->toplevel()) {		Scheduler* s;		if ((s = &Scheduler::instance()) != NULL)			cbq_->toplevel_arrival(this, s->clock());	}	send(pkt, h);	// queue packet downstream	if (!cbq_->blocked()) {		cbq_->sched();	}	return;}/* * update a class' statistics and all parent classes * up to the root */void CBQClass::update(Packet* p, double now){	double idle, avgidle;	hdr_cmn* hdr = hdr_cmn::access(p);	int pktsize = hdr->size();	double tx_time = cbq_->link()->txtime(p);	double fin_time = now + tx_time;	idle = (fin_time - last_time_) - (pktsize / maxrate_);	avgidle = avgidle_;	avgidle += (idle - avgidle) / POWEROFTWO;	if (maxidle_ < 0) {		fprintf(stderr,			"CBQClass: warning: maxidle_ not configured!\n");	} else if (avgidle > maxidle_)		avgidle = maxidle_;	avgidle_ = avgidle;	if (avgidle <= 0) {		undertime_ = fin_time + tx_time *			(1.0 / allotment_ - 1.0);		undertime_ += (1-POWEROFTWO) * avgidle;	}	last_time_ = fin_time;	// tail-recurse up to root of tree performing updates	if (lender_)		lender_->update(p, now);	return;}/* * satisfied: is this class satisfied? */intCBQClass::satisfied(double now){	if (leaf()) {		/* leaf is unsat if underlimit with backlog */		if (undertime_ < now && demand())			return (0);		else			return (1);	}	if (undertime_ < now && desc_with_demand())		return (0);	return (1);}/* * desc_with_demand: is there a descendant of this class with demand *	really, is there a leaf which is a descendant of me with *	a backlog */intCBQClass::desc_with_demand(){	CBQClass *p = cbq_->level(LEAF_LEVEL);	for (; p != NULL; p = p->level_peer_) {		if (p->demand() && ancestor(p))			return (1);	}	return (0);}/* * happens when a class is unable to send because it * is being regulated */void CBQClass::delayed(double now){	double delay = undertime_ - now + extradelay_;	if (delay > 0 && !delayed_) {		undertime_ += extradelay_;		undertime_ -= (1-POWEROFTWO) * avgidle_;		delayed_ = 1;	}}/* * return 1 if we are an ancestor of p, 0 otherwise */intCBQClass::ancestor(CBQClass *p){	if (!p->permit_borrowing_ || p->lender_ == NULL)		return (0);	else if (p->lender_ == this)		return (1);	return (ancestor(p->lender_));}/* * change an allotment */voidCBQClass::newallot(double bw){        if (allotment_ < 0)                allotment_ = 0;        if (bw < 0)                bw = 0;	maxrate_ = bw * ( cbq_->link()->bandwidth() / 8.0 );	double diff = bw - allotment_;	allotment_ = bw;	cbq_->addallot(pri_, diff);	return;}/* * OTcl Interface *//*  * $class1 parent $class2 * $class1 borrow $class2 * $class1 qdisc $queue * $class1 allot * $class1 allot new-bw */int CBQClass::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 2) {		if (strcmp(argv[1], "allot") == 0) {			tcl.resultf("%g", allotment_);			return (TCL_OK);		}		if (strcmp(argv[1], "cbq") == 0) {			if (cbq_ != NULL)				tcl.resultf("%s", cbq_->name());			else				tcl.resultf("");			return(TCL_OK);		}		if (strcmp(argv[1], "qdisc") == 0) {			if (q_ != NULL)				tcl.resultf("%s", q_->name());			else				tcl.resultf("");			return (TCL_OK);		}		if (strcmp(argv[1], "qmon") == 0) {			if (qmon_ != NULL)				tcl.resultf("%s", qmon_->name());			else				tcl.resultf("");			return (TCL_OK);		}	} else if (argc == 3) {		// for now these are the same		if ((strcmp(argv[1], "parent") == 0)) {			if (strcmp(argv[2], "none") == 0) {				lender_ = NULL;				return (TCL_OK);			}			lender_ = (CBQClass*)TclObject::lookup(argv[2]);			if (lender_ != NULL)				return (TCL_OK);			return (TCL_ERROR);		}		if (strcmp(argv[1], "qdisc") == 0) {			q_ = (Queue*) TclObject::lookup(argv[2]);			if (q_ != NULL)				return (TCL_OK);			tcl.resultf("couldn't find object %s",				argv[2]);			return (TCL_ERROR);		}		if (strcmp(argv[1], "qmon") == 0) {			qmon_ = (QueueMonitor*) TclObject::lookup(argv[2]);			if (qmon_ != NULL)				return (TCL_OK);			return (TCL_ERROR);		}		if (strcmp(argv[1], "allot") == 0) {			double bw = atof(argv[2]);			if (bw < 0.0)				return (TCL_ERROR);			if (allotment_ != 0.0) {				tcl.resultf(" class %s already has allotment of %f!",					    name(), allotment_);				return (TCL_ERROR);			}			allotment_ = bw;			return (TCL_OK);		}		if (strcmp(argv[1], "newallot") == 0) {			double bw = atof(argv[2]);			if (bw < 0.0)				return (TCL_ERROR);			newallot(bw);			return (TCL_OK);		}		if (strcmp(argv[1], "maxidle") == 0) {			double m = atof(argv[2]);			if (m < 0.0) {				tcl.resultf("invalid maxidle value %s (must be non-negative)",					    argv[2]);				return (TCL_ERROR);			}			maxidle_ = m;			return (TCL_OK);		}	}	return (Connector::command(argc, argv));}

⌨️ 快捷键说明

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