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

📄 mac-802_11e.cc

📁 在网络仿真模拟工具下实现支持QoS的MAC层EDCF协议
💻 CC
📖 第 1 页 / 共 3 页
字号:
#undef NDEBUG#include <assert.h>#include "delay.h"#include "connector.h"#include "packet.h"#include "random.h"#include "mobilenode.h"#include "stream.h"#include "arp.h"#include "ll.h"#include "mac.h"#include "mac-timers_802_11e.h"#include "mac-802_11e.h"#include "cmu-trace.h"#include "priq.h"//include the following line when using Akaroa//#include "akaroa.H"#define AKAROA 0 #define INTERVAL 0.01 // XXX Can't we make these macros inline methods? Otherwise why should we have// inline methods at all??#define CHECK_BACKOFF_TIMER() 					                \{									        \	if(is_idle() && mhBackoff_.paused()) { 				        \            mhBackoff_.resume();				                \	}                                                                       \	if(! is_idle() && mhBackoff_.busy() && ! mhBackoff_.paused()){	        \		mhBackoff_.pause();					        \        }                                                                       \ if(!is_idle() && mhDefer_.busy()) mhDefer_.stop();                             \}inline voidMac802_11e::transmit(Packet *p, double t){                                                                       	/*                                                                       * If I'm transmitting without doing CS, such as when                    * sending an ACK, any incoming packet will be "missed"                  * and hence, must be discarded.                                         */                                                                      if(rx_state_ != MAC_IDLE) {                                                     struct hdr_mac802_11 *dh = HDR_MAC802_11(p);                                                                                                    assert(dh->dh_fc.fc_type == MAC_Type_Control);                          assert(dh->dh_fc.fc_subtype == MAC_Subtype_ACK);                                                                                                assert(pktRx_);                                                         struct hdr_cmn *ch = HDR_CMN(pktRx_);                                                                                                           ch->error() = 1;        /* force packet discard */              }                                                                                                                                               /*                                                                       * pass the packet on the "interface" which will in turn                 * place the packet on the channel.                                      *                                                                       * NOTE: a handler is passed along so that the Network                   *       Interface can distinguish between incoming and                  *       outgoing packets.                                               */	struct hdr_cmn *sd = HDR_CMN(p);	int prio = LEVEL(p);	tx_active_ = 1;	sending = 1;	CHECK_BACKOFF_TIMER();	downtarget_->recv(p->copy(), this);	if(sd->ptype() == PT_CBR || sd->ptype() == PT_EXP) {	  if(!rtx_[prio]){	    numbytes_[prio] += sd->size() - ETHER_HDR_LEN11;	  }	} 	mhIF_.start(txtime(p));  	mhSend_.start(t);                      	                                       } #define SET_RX_STATE(x) 		                            \{	                                                            \	rx_state_ = x;		                                    \	CHECK_BACKOFF_TIMER();  	                            \}#define SET_TX_STATE(pri, x)			                    \{						                    \	tx_state_[pri] = x;			                    \}/* ======================================================================   Global Variables   ====================================================================== */static EDCF_PHY_MIB EDCF_PMIB ={        DSSS_EDCF_SlotTime, DSSS_EDCF_CCATime,	DSSS_EDCF_RxTxTurnaroundTime, DSSS_EDCF_SIFSTime, DSSS_EDCF_PreambleLength,	DSSS_EDCF_PLCPHeaderLength, DSSS_EDCF_PLCPDataRate};	static MAC_MIB EDCF_MMIB ={	MAC_EDCF_RTSThreshold, MAC_EDCF_ShortRetryLimit,	MAC_EDCF_LongRetryLimit, MAC_EDCF_FragmentationThreshold,	MAC_EDCF_MaxTransmitMSDULifetime, MAC_EDCF_MaxReceiveLifetime,	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};/* ======================================================================   TCL Hooks for the simulator   ====================================================================== */static class Mac802_11eClass : public TclClass {public:	Mac802_11eClass() : TclClass("Mac/802_11e") {}	TclObject* create(int, const char*const*) {		return (new Mac802_11e(&EDCF_PMIB, &EDCF_MMIB));	}} class_mac802_11e;/* ======================================================================   Mac Class Functions   ====================================================================== */Mac802_11e::Mac802_11e(EDCF_PHY_MIB *p, MAC_MIB *m) : Mac(), mhIF_(this), mhNav_(this), mhRecv_(this), mhSend_(this), mhDefer_(this, p->SlotTime), mhSifs_(this, p->SlotTime), mhBackoff_(this, p->SlotTime), AK(this){        // Pointer to PriQ, Cast in priq.cc	queue_  = 0;		//flags to control if PriQ Parameters have already been adopted	AIFSset = 0;	CWset   = 0;	for(int i=0; i < MAX_PRI; i++){	    packets_[i] = 0;	    pktRTS_[i] = 0;	    pktCTRL_[i] = 0;	    pktTx_[i] = 0;	    tx_state_[i] = MAC_IDLE;	    ssrc_[i] = slrc_[i] = 0;	    callback_[i] = 0;	    numbytes_[i] = 0;	    rtx_[i] = 0;	    cw_[i] = 0;	    cwmin_[i] = 0;	    cwmax_[i] = 0;	    aifs_[i] = 0;	    txop_limit_[i] = 0;	}         jitter  =    1000;	//jitter =   0;	throughput = 0;	interval_ =  INTERVAL;        if(AKAROA) AK.start();	macmib_ =    m;	phymib_ =    p;		nav_ =       0.0;		rx_state_ =  MAC_IDLE;	tx_active_ = 0;          		idle_time =     0;	sending =       0;	cfb_dur =       0;	cfb_active =    0;        cfb_broadcast = 0;		levels =     0;	slotnum =    0;	pf =         0;	cw_old =     0;	sifs_ = phymib_->SIFSTime;	pifs_ = sifs_ + phymib_->SlotTime;	difs_ = sifs_ + 2*phymib_->SlotTime;		        // see (802.11-1999, 9.2.10) 	eifs_ = sifs_ + (8 * ETHER_ACK_LEN / phymib_->PLCPDataRate);//	eifs_ = sifs_ + (8 * ETHER_ACK_LEN / phymib_->PLCPDataRate) + difs_;		eifs_nav_ =  0;	//tx_sifs_ = sifs_ - phymib_->RxTxTurnaroundTime;	//tx_pifs_ = tx_sifs_ + phymib_->SlotTime;	//tx_difs_ = tx_sifs_ + 2 * phymib_->SlotTime;		sta_seqno_ =        1;	cache_ =            0;	cache_node_count_ = 0;	        // chk if basic/data rates are set	// otherwise use bandwidth_ as default;		Tcl& tcl = Tcl::instance();	tcl.evalf("Mac/802_11e set basicRate_");	if (strcmp(tcl.result(), "0") != 0) 		bind_bw("basicRate_", &basicRate_);	else	    basicRate_ = bandwidth_;	tcl.evalf("Mac/802_11e set dataRate_");	if (strcmp(tcl.result(), "0") != 0) 	  bind_bw("dataRate_", &dataRate_);	else	  dataRate_ = bandwidth_;	  	tcl.evalf("Mac/802_11e set rst_cw_mode_");	if (strcmp(tcl.result(), "0") != 0) 	  bind("rst_cw_mode_", &rst_cw_mode_);	else	  rst_cw_mode_=0;	  		bind("cfb_", &cfb_);}intMac802_11e::command(int argc, const char*const* argv){	if (argc == 3) {	    if (strcmp(argv[1], "log-target") == 0) {		logtarget_ = (NsObject*) TclObject::lookup(argv[2]);		if(logtarget_ == 0)		    return TCL_ERROR;		return TCL_OK;	    } else if(strcmp(argv[1], "nodes") == 0) {		if(cache_) return TCL_ERROR;		cache_node_count_ = atoi(argv[2]);		cache_ = new Host[cache_node_count_ + 1];		assert(cache_);		bzero(cache_, sizeof(Host) * (cache_node_count_+1 ));		return TCL_OK;	    }	}	// wiethoelter, 28.07.03	// VOIP-Projekt        // Zugriff auf das RetryLimit des MAC-Layers vom RTPData-Agent aus        Tcl& tcl = Tcl::instance();        if ( argc == 2 ) {                if ( strcmp( argv[1], "set_RetryLimit" ) == 0 ) {                        tcl.resultf( "%d", macmib_->ShortRetryLimit );                        return TCL_OK;                }        }        if ( argc == 3 ) {                if ( strcmp( argv[1], "set_RetryLimit" ) == 0 ) {                        macmib_->ShortRetryLimit = atoi( argv[2] );;                        return TCL_OK;                }        }	return Mac::command(argc, argv);}/* ======================================================================   Debugging Routines   ====================================================================== *//* * dump and packet trace are not adopted to 802.11e yet! */voidMac802_11e::trace_pkt(Packet *p) {	struct hdr_cmn *ch = HDR_CMN(p);	struct hdr_mac802_11* dh = HDR_MAC802_11(p);	u_int16_t *t = (u_int16_t*) &dh->dh_fc;	fprintf(stderr, "\t[ %2x %2x %2x %2x ] %x %s %d\n",		*t, dh->dh_duration,		ETHER_ADDR(dh->dh_da), ETHER_ADDR(dh->dh_sa),		index_, packet_info.name(ch->ptype()), ch->size());}voidMac802_11e::dump(char *fname){	fprintf(stderr,		"\n%s --- (INDEX: %d, time: %2.9f)\n",		fname, index_, Scheduler::instance().clock());	fprintf(stderr,		"\ttx_state_: %x, rx_state_: %x, nav: %2.9f, idle: %d\n",		tx_state_, rx_state_, nav_, is_idle());	fprintf(stderr,		"\tpktTx_: %x, pktRx_: %x, pktRTS_: %x, pktCTRL_: %x, callback: %x\n",		(int) pktTx_, (int) pktRx_, (int) pktRTS_,		(int) pktCTRL_, (int) callback_);	fprintf(stderr,		"\tDefer: %d, Backoff: %d (%d), Recv: %d, Timer: %d Nav: %d\n",		mhDefer_.busy(), mhBackoff_.busy(), mhBackoff_.paused(),		mhRecv_.busy(), mhSend_.busy(), mhNav_.busy());	fprintf(stderr,		"\tBackoff Expire: %f\n",		mhBackoff_.expire());}/* ======================================================================   Packet Headers Routines   ====================================================================== */inline intMac802_11e::hdr_dst(char* hdr, int dst ){	struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr;	//dst = (u_int32_t)(dst);	if(dst > -2)		STORE4BYTE(&dst, (dh->dh_da));	return ETHER_ADDR(dh->dh_da);}inline int Mac802_11e::hdr_src(char* hdr, int src ){	struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr;	if(src > -2)		STORE4BYTE(&src, (dh->dh_sa));	return ETHER_ADDR(dh->dh_sa);}inline int Mac802_11e::hdr_type(char* hdr, u_int16_t type){	struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr;	if(type)		STORE2BYTE(&type,(dh->dh_body));	return GET2BYTE(dh->dh_body);}/* ======================================================================   Misc Routines   ====================================================================== */inline intMac802_11e::is_idle(){    if(rx_state_ != MAC_IDLE){      idle_time = 0;      return 0;    }    if(sending) {      idle_time = 0;      return 0;    }        if(nav_ > Scheduler::instance().clock()){      idle_time = 0;      return 0;    }    idle_time = Scheduler::instance().clock();    return 1;}voidMac802_11e::discard(Packet *p, const char* why){	hdr_mac802_11* mh = HDR_MAC802_11(p);	hdr_cmn *ch = HDR_CMN(p);#if 0	/* old logic 8/8/98 -dam */	/*	 * If received below the RXThreshold, then just free.	 */	if(p->txinfo_.Pr < p->txinfo_.ant.RXThresh) {		Packet::free(p);		//p = 0;		return;	}#endif // 0	/* if the rcvd pkt contains errors, a real MAC layer couldn't	   necessarily read any data from it, so we just toss it now */	if(ch->error() != 0) {		Packet::free(p);		//p = 0;		return;	}	switch(mh->dh_fc.fc_type) {	case MAC_Type_Management:		drop(p, why);		return;	case MAC_Type_Control:		switch(mh->dh_fc.fc_subtype) {		case MAC_Subtype_RTS:			if((u_int32_t)ETHER_ADDR(mh->dh_sa) == \			   (u_int32_t)index_) {				drop(p, why);				return;			}			/* fall through - if necessary */		case MAC_Subtype_CTS:		case MAC_Subtype_ACK:			if((u_int32_t)ETHER_ADDR(mh->dh_da) == \			   (u_int32_t)index_) {				drop(p, why);				return;			}			break;		default:			fprintf(stderr, "invalid MAC Control subtype\n");			exit(1);		}		break;	case MAC_Type_Data:		switch(mh->dh_fc.fc_subtype) {		case MAC_Subtype_Data:			if((u_int32_t)ETHER_ADDR(mh->dh_da) == \			   (u_int32_t)index_ ||			   (u_int32_t)ETHER_ADDR(mh->dh_sa) == \			   (u_int32_t)index_ ||			   (u_int32_t)ETHER_ADDR(mh->dh_da) == MAC_BROADCAST) {				drop(p);				return;			}			break;		default:			fprintf(stderr, "invalid MAC Data subtype\n");			exit(1);		}		break;	default:		fprintf(stderr, "invalid MAC type (%x)\n", mh->dh_fc.fc_type);		trace_pkt(p);		exit(1);	}	Packet::free(p);}voidMac802_11e::capture(Packet *p){	/*	 * Update the NAV so that this does not screw	 * up carrier sense.	 */    	set_nav(usec(eifs_ + txtime(p)));		      Packet::free(p);}voidMac802_11e::collision(Packet *p){	switch(rx_state_) {	case MAC_RECV:		SET_RX_STATE(MAC_COLL);		/* fall through */	case MAC_COLL:		assert(pktRx_);		assert(mhRecv_.busy());		/*		 *  Since a collision has occurred, figure out		 *  which packet that caused the collision will		 *  "last" the longest.  Make this packet,		 *  pktRx_ and reset the Recv Timer if necessary.		 */		if(txtime(p) > mhRecv_.expire()) {			mhRecv_.stop();			discard(pktRx_, DROP_MAC_COLLISION);			pktRx_ = p;			mhRecv_.start(txtime(pktRx_));		}		else {			discard(p, DROP_MAC_COLLISION);		}		break;	default:		assert(0);	}}voidMac802_11e::tx_resume(){	double rTime;	assert(mhSend_.busy() == 0);		for(int pri = 0; pri < MAX_PRI; pri++){	    //assert(mhDefer_.defer(pri) == 0);	    if(!mhDefer_.defer(pri)) {		if(pktCTRL_[pri]) {		/*		 *  Need to send a CTS or ACK.		 */		    mhSifs_.start(pri, sifs_);		} else if(pktRTS_[pri]) {		    if(mhBackoff_.backoff(pri) == 0) {		      rTime = (Random::random() % getCW(LEVEL(pktRTS_[pri]))) * phymib_->SlotTime;		      mhDefer_.start(pri, getAIFS(LEVEL(pktRTS_[pri]))); 		    }		} else if(pktTx_[pri]) {		    if(mhBackoff_.backoff(pri) == 0) {			hdr_cmn *ch = HDR_CMN(pktTx_[pri]);			struct hdr_mac802_11 *mh = HDR_MAC802_11(pktTx_[pri]);						if ((u_int32_t) ch->size() < macmib_->RTSThreshold ||			    (u_int32_t) ETHER_ADDR(mh->dh_da) == MAC_BROADCAST) {			  			  if((u_int32_t) ETHER_ADDR(mh->dh_da) == MAC_BROADCAST) rTime = (Random::random() % (getCW(pri) + 1)) * phymib_->SlotTime;			  else rTime = 0;			    mhDefer_.start(pri, getAIFS(pri) + rTime);			} else {			    mhSifs_.start(pri, sifs_); 			}		    }		} else if(callback_[pri] != 0) {		  rtx_[pri] = 0;		  Handler *h = callback_[pri];		  callback_[pri] = 0;		  h->handle((Event*) 0);		}		SET_TX_STATE(pri, MAC_IDLE);	    }	}}voidMac802_11e::rx_resume(){  assert(pktRx_ == 0);    assert(mhRecv_.busy() == 0);    SET_RX_STATE(MAC_IDLE);}/* ======================================================================   Timer Handler Routines   ====================================================================== */voidMac802_11e::backoffHandler(int pri){   if(pktCTRL_[pri]) {    assert(mhSend_.busy() || mhDefer_.defer(pri));    return;  }    if(check_pktRTS(pri) == 0)    return;    if(check_pktTx(pri) == 0)    return;}voidMac802_11e::deferHandler(int pri){	assert(pktCTRL_[pri] || pktRTS_[pri] || pktTx_[pri]);	if(check_pktCTRL(pri) == 0)		return;	assert(mhBackoff_.backoff(pri) == 0);	//if (mhBackoff_.busy() != 0)	//{	//	printf("deferHandler:mhBackoff_ busy!\n");	//	return;	//}	if(check_pktRTS(pri) == 0)		return;	if(check_pktTx(pri) == 0)		return;}voidMac802_11e::navHandler(){    eifs_nav_ = 0.0;    if(is_idle() && mhBackoff_.paused()) {		mhBackoff_.resume();    }}voidMac802_11e::recvHandler(){    	recv_timer();}voidMac802_11e::sendHandler(){    Scheduler &s = Scheduler::instance();    sending = 0;    CHECK_BACKOFF_TIMER();    send_timer();}void

⌨️ 快捷键说明

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