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

📄 mac-timers_802_11e.cc

📁 在网络仿真模拟工具下实现支持QoS的MAC层EDCF协议
💻 CC
字号:
//* -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* * Copyright (c) 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. *//* Ported from CMU/Monarch's code, nov'98 -Padma.*/#undef NDEBUG#include <assert.h>#include <delay.h>#include <connector.h>#include <packet.h>#include <random.h>#include <iostream.h>#define DEBUG_ 0#define BACKOFF_CHECK 0//#include <debug.h>#include <arp.h>#include <ll.h>#include <mac.h>#include <mac/802_11e/mac-timers_802_11e.h>#include <mac/802_11e/mac-802_11e.h> #define inf   (1e12)#define round (1e-12)/* * Force timers to expire on slottime boundries. */// #define USE_SLOT_TIME#define ROUND_TIME()	\	{								\		assert(slottime);					\		double rmd = remainder(s.clock() + rtime, slottime);	\		if(rmd > 0.0)						\			rtime += (slottime - rmd);			\		else							\			rtime += (-rmd);				\	}/* ======================================================================   Timers   ====================================================================== */voidMacTimer_802_11e::start(double time){	Scheduler &s = Scheduler::instance();	assert(busy_ == 0);	busy_ = 1;	paused_ = 0;	stime = s.clock();	rtime = time;	assert(rtime >= 0.0);	s.schedule(this, &intr, rtime);}voidMacTimer_802_11e::stop(void){	Scheduler &s = Scheduler::instance();	assert(busy_);	if(paused_ == 0)		s.cancel(&intr);	busy_ = 0;	paused_ = 0;	stime = 0.0;	rtime = 0.0;}/* ======================================================================   Defer Timer   ====================================================================== */voidDeferTimer_802_11e::start(int pri, double time){	Scheduler &s = Scheduler::instance();	int another = 0;	assert(defer_[pri] == 0);	for(int i = 0; i < MAX_PRI; i++ ){			if(defer_[i] && busy_) {			another = 1;		}	}		if(another){		pause();	}	busy_ = 1;	defer_[pri] = 1;	stime_[pri] = s.clock();	rtime_[pri] = time; 	double delay = inf;	int prio = MAX_PRI + 1;	for(int pri = 0; pri < MAX_PRI; pri++){		if(defer_[pri]){			stime_[pri] = s.clock();			double delay_ = rtime_[pri]; 			if((delay_ < delay)) {				delay = delay_;				prio = pri;			}		}	}	if(prio < MAX_PRI + 1) {		assert(rtime_[prio] >=0);		s.schedule(this, &intr, rtime_[prio]);		paused_ = 0;	} else {		exit(0);	}}void DeferTimer_802_11e::stop(){	busy_ = 0;	for(int pri = 0; pri < MAX_PRI;pri++){		if(defer_[pri]) mac->defer_stop(pri);		defer_[pri] = 0;		stime_[pri] = 0;		rtime_[pri] = 0;			}	Scheduler &s = Scheduler::instance();	s.cancel(&intr);}voidDeferTimer_802_11e::pause(){	Scheduler &s = Scheduler::instance();	for(int pri = 0; pri < MAX_PRI; pri++ ){			if(defer_[pri] && busy_){			double st = s.clock();            //now			double rt = stime_[pri];   // Start-Time of defer			double sr = st - rt;			assert(busy_ && ! paused_);			if(rtime_[pri] - sr >= 0.0) {				rtime_[pri] -= sr;				assert(rtime_[pri] >= 0.0);				} else{				if(rtime_[pri] + round - sr >= 0.0){ 					rtime_[pri] = 0;				} else {					cout<<"ERROR in DeferTimer::pause(), rtime_["<<pri<<"]  is "<<rtime_[pri]<<", sr:"<<sr<<"  \n";					exit(0);				}			}		}	}	s.cancel(&intr);	paused_ = 1;}void    DeferTimer_802_11e::handle(Event *){       	Scheduler &s = Scheduler::instance();	double delay = inf;	int prio = MAX_PRI + 1;	for( int pri = 0; pri < MAX_PRI; pri++) {				if(rtime_[pri] >= 0 && defer_[pri]){						double delay_ = rtime_[pri];			if((delay_ < delay) && defer_[pri]) {				delay = delay_;				prio = pri;			}		}	}	if(prio < MAX_PRI + 1){		busy_ = 0;		paused_ = 0;		defer_[prio] = 0;		stime_[prio] = 0.0;		rtime_[prio] = 0.0;		mac->deferHandler(prio);	} else {		cout<<"handling ERROR in DeferTimer::handler \n"; 		exit(0);	}	        //check if there is another DeferTimer active	for( int pri = 0; pri < MAX_PRI; pri++) {		if(rtime_[pri] >= 0 && defer_[pri]){		  rtime_[pri] = 0.0;		  stime_[pri] = 0.0;		  defer_[pri] = 0;		  mac->defer_stop(pri);		}	}	}intDeferTimer_802_11e::defer(int pri) {	return defer_[pri];}/* ======================================================================   NAV Timer   ====================================================================== */void    NavTimer_802_11e::handle(Event *){       	busy_ = 0;	paused_ = 0;	stime = 0.0;	rtime = 0.0;	mac->navHandler();}/* ======================================================================   Receive Timer   ====================================================================== */void    RxTimer_802_11e::handle(Event *){       	busy_ = 0;	paused_ = 0;	stime = 0.0;	rtime = 0.0;	mac->recvHandler();}/* ======================================================================   Send Timer   ====================================================================== */void    TxTimer_802_11e::handle(Event *){       	busy_ = 0;	paused_ = 0;	stime = 0.0;	rtime = 0.0;	mac->sendHandler();}/* ======================================================================   Interface Timer   ====================================================================== */voidIFTimer_802_11e::handle(Event *){	Scheduler &s = Scheduler::instance();	busy_ = 0;	paused_ = 0;	stime = 0.0;	rtime = 0.0;	mac->txHandler();	}/* ====================================================================== Defer Timer for SIFS   ====================================================================== */voidSIFSTimer_802_11e::start(int pri, double time){	Scheduler &s = Scheduler::instance();	if(busy_ == 1){cout<<"Mac "<<mac->index_<<", ERROR in SIFSTimer!"; exit(0);}	assert(sifs_[pri] == 0);		busy_ = 1;        sifs_[pri] = 1;	stime_[pri] = s.clock();	rtime_[pri] = time; 	s.schedule(this, &intr, rtime_[pri]);}voidSIFSTimer_802_11e::handle(Event *){	Scheduler &s = Scheduler::instance();	busy_ = 0;	prio = 0;			for(int pri = 0; pri < MAX_PRI; pri++){		if(sifs_[pri]) { 			prio = pri;			break;		}	}		for(int i = 0; i < MAX_PRI; i++){			sifs_[i]  = 0;		stime_[i] = 0.0;		rtime_[i] = 0.0;	}	mac->deferHandler(prio);	}/* ======================================================================   Backoff Timer   ====================================================================== */inline void BackoffTimer_802_11e::round_time(int pri){		double rmd = remainder(rtime_[pri], mac->phymib_->SlotTime);		if(rmd<0){			rmd = 0;		}		assert(rmd>=0);		if(rmd < (mac->phymib_->SlotTime /10))									if(rtime_[pri] -rmd >= 0) rtime_[pri] -= rmd;		        else rtime_[pri] = 0;		else if(rmd > (mac->phymib_->SlotTime - (mac->phymib_->SlotTime /10)))									rtime_[pri] += (mac->phymib_->SlotTime - rmd);		else{			cout<<"ERROR in Backoff::round_time(): Mac "<<mac->index_<<" rtime_["<<pri<<"] is "<<rtime_[pri]<<", remainder: "<<rmd<<"\n";			exit(3);		}}voidBackoffTimer_802_11e::handle(Event *){	Scheduler &s = Scheduler::instance();	paused_ = 0;	double delay = inf;	int prio = MAX_PRI + 1;		for(int pri = 0; pri < MAX_PRI; pri++){				double delay_ = rtime_[pri] + AIFSwait_[pri];		if((delay_ < delay) && backoff_[pri]) {			delay = delay_;			prio = pri;		}	}	if(prio < MAX_PRI + 1) {			busy_ = 0;		        stime_[prio] = 0;			rtime_[prio] = 0;			backoff_[prio] = 0;			AIFSwait_[prio] = 0.0;		//mac->backoffHandler(prio); now done further down at the end of Handler!		} else {		cout<<"ERROR: wrong priority in BackoffTimer::handler()";		exit(0);	}		busy_ = 0;	for(int pri = 0; pri < MAX_PRI; pri++){		if(backoff_[pri]) { //check if there is another backoff process			busy_ = 1;				if(rtime_[pri] + AIFSwait_[pri] == delay) {				mac->inc_cw(pri);				AIFSwait_[pri] = 0;				stime_[pri] = s.clock(); //Start-Time				rtime_[pri] = (Random::random() % (mac->getCW(pri) + 1)) * mac->phymib_->SlotTime; 				backoff_[pri] = 1;			} 		}	}	        if(busy_ && !paused_){		pause(); //pause + restart because the backoff could be a postbackoff!		restart();	}	mac->backoffHandler(prio);	}voidBackoffTimer_802_11e::start(int pri, int cw, int idle){	Scheduler &s = Scheduler::instance();		if(busy_) { //already a backoff running!		offset_[pri] = 0;		stime_[pri] = s.clock(); //Start-Time		rtime_[pri] = (Random::random() % (cw + 1)) * mac->phymib_->SlotTime;		AIFSwait_[pri] = 0.0;		backoff_[pri] = 1;		if(idle == 0){			if(!paused_){				pause();			}		}		else {			assert(rtime_[pri] >= 0.0);			if(!paused_) {				pause();				AIFSwait_[pri] = mac->getAIFS(pri); 				//cout<<"Mac "<<mac->index_<<": now: "<<Scheduler::instance().clock()<<"pause and restart for prio "<<pri<<"\n";				restart();			}		}	} else {		backoff_[pri] = 1;		busy_ = 1;		offset_[pri] = 0;		stime_[pri] = s.clock(); //Start-Time		rtime_[pri] = (Random::random() % (cw + 1)) * mac->phymib_->SlotTime;		AIFSwait_[pri] = mac->getAIFS(pri);  		if(idle == 0){			paused_ = 1;		}		else {			assert(rtime_[pri] >= 0.0);			s.schedule(this, &intr, rtime_[pri] + AIFSwait_[pri]);		}	}}voidBackoffTimer_802_11e::pause(){	Scheduler &s = Scheduler::instance();	//the caculation below make validation pass for linux though it	// looks dummy	for (int pri = 0; pri < MAX_PRI; pri++) {		if(backoff_[pri]) {			double st = s.clock();            //now			double rt = stime_[pri] + AIFSwait_[pri]; // Start-Time des Backoffs + waiting time			double sr = st - rt;			double mst = (mac->phymib_->SlotTime);			int slots = int (sr/mst); 			if(slots < 0)				slots = 0;			if(sr >= 0) offset_[pri] = sr - (slots * mst);				assert(offset_[pri] >= 0);			assert(busy_ && ! paused_);			if(rtime_[pri] - (slots * mac->phymib_->SlotTime) >= 0.0) {				rtime_[pri] -= (slots * mac->phymib_->SlotTime);				assert(rtime_[pri] >= 0.0);				} else{				if(rtime_[pri] + round - (slots * mac->phymib_->SlotTime) >= 0.0) { 					rtime_[pri] = 0;				} else {					cout<<"ERROR in BackoffTimer::pause(), rtime_["<<pri<<"]  is "<<rtime_[pri]<<", slots: "<<slots<<", SlotTime: "<<mac->phymib_->SlotTime<<"  \n";					exit(0);				}				}			if(st - stime_[pri] >= mac->getAIFS(pri)) AIFSwait_[pri] = 0.0;			else{				AIFSwait_[pri] -= st - stime_[pri];				if(AIFSwait_[pri] < 0) AIFSwait_[pri] = 0;				//cout<<"Mac "<<mac->index_<<", now: "<<Scheduler::instance().clock()<<", setting AIFSwait_["<<pri<<"] to "<<AIFSwait_[pri]<<"\n";			}		}	}	s.cancel(&intr);	paused_ = 1;}voidBackoffTimer_802_11e::resume(){	double delay = inf;	int prio = MAX_PRI + 1;	Scheduler &s = Scheduler::instance();		for(int pri = 0; pri < MAX_PRI; pri++){		if(backoff_[pri]){			offset_[pri] = 0;			round_time(pri);			AIFSwait_[pri] = mac->getAIFS(pri);			stime_[pri] = s.clock();			double delay_ = rtime_[pri] + AIFSwait_[pri];			if((delay_ < delay) && backoff_[pri]) {				delay = delay_;				prio = pri;			}		}	}	if(prio < MAX_PRI + 1) {		assert(rtime_[prio] + AIFSwait_[prio] >=0);		s.schedule(this, &intr, rtime_[prio] + AIFSwait_[prio]);		paused_ = 0;	} else {		cout<<"ERROR: wrong priority in BackoffTimer::resume() \n";		exit(0);	}}voidBackoffTimer_802_11e::restart(){	busy_ = 1;	double delay = inf;	int prio = MAX_PRI + 1;	Scheduler &s = Scheduler::instance();		for(int pri = 0; pri < MAX_PRI; pri++){		if(backoff_[pri]) {			if(rtime_[pri] > offset_[pri]) rtime_[pri] -= offset_[pri];			offset_[pri] = 0;			round_time(pri);			stime_[pri] = s.clock();			double delay_ = rtime_[pri] + AIFSwait_[pri];			if(delay_ < delay) {				delay = delay_;				prio = pri;			}		}	}	if(prio < MAX_PRI + 1) {		assert(rtime_[prio] + AIFSwait_[prio] >=0);		s.schedule(this, &intr, rtime_[prio] + AIFSwait_[prio]);		paused_ = 0;	} else {		cout<<"ERROR: wrong priority in BackoffTimer::restart() \n";		exit(0);	}}intBackoffTimer_802_11e::backoff(int pri){	return backoff_[pri];}/* * Timer for throughput measurement  */ void AkaroaTimer::start(){	Scheduler &s = Scheduler::instance();	s.schedule(this, &intr,mac->interval_);}void AkaroaTimer::handle(Event *){	mac->calc_throughput();}

⌨️ 快捷键说明

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