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

📄 mac-802_11.cc

📁 多信道多接口无线mesh网络MAC协议MMAC的ns2仿真源码
💻 CC
📖 第 1 页 / 共 5 页
字号:
/* -*-	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. * * $Header: /nfs/jade/vint/CVSROOT/ns-2/mac/mac-802_11.cc,v 1.39 2002/03/14 01:12:53 haldar Exp $ * * Ported from CMU/Monarch's code, nov'98 -Padma. */#include "delay.h"#include "connector.h"#include "packet.h"#include "random.h"#include "mobilenode.h"// #define DEBUG 99#include "arp.h"#include "ll.h"#include "mac.h"#include "mac-timers.h"#include "mac-802_11.h"#include "cmu-trace.h"// XXX Can't we make these macros inline methods? Otherwise why should we have// inline methods at all??#define BEACON_BACKOFF_WINDOW 	32//#define	ATIM_WINDOW	0.02#define DEFAULT_CHANNEL 0#define CHECK_BACKOFF_TIMER()						\{									\	if(is_idle() && mhBackoff_.paused())				\		mhBackoff_.resume(difs_);				\	if(! is_idle() && mhBackoff_.busy() && ! mhBackoff_.paused())	\		mhBackoff_.pause();					\}#define TRANSMIT(p, t)                                                  \{                                                                       \	tx_active_ = 1;                                                  \                                                                        \        /*                                                              \         * 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.                                      \         */                                                             \	downtarget_->recv(p->copy(), this);				\        mhSend_.start(t);                                                \                                                                        \	mhIF_.start(txtime(p));                                         \}//It was p->copy(), 8 lines above#define SET_RX_STATE(x)			\{					\	rx_state_ = (x);		\	CHECK_BACKOFF_TIMER();		\}#define SET_TX_STATE(x)				\{						\	tx_state_ = (x);			\	CHECK_BACKOFF_TIMER();			\}#define SET_DX_STATE(x)				\{						\	dx_state_ = (x);			\	CHECK_BACKOFF_TIMER();			\}/* ======================================================================   Global Variables   ====================================================================== */static PHY_MIB PMIB ={	DSSS_CWMin, DSSS_CWMax, DSSS_SlotTime, DSSS_CCATime,	DSSS_RxTxTurnaroundTime, DSSS_SIFSTime, DSSS_PreambleLength,	DSSS_PLCPHeaderLength, DSSS_PLCPDataRate};	static MAC_MIB MMIB ={	MAC_RTSThreshold, MAC_ShortRetryLimit,	MAC_LongRetryLimit, MAC_FragmentationThreshold,	MAC_MaxTransmitMSDULifetime, MAC_MaxReceiveLifetime,//JUNGMIN	100 /* BeaconPeriod */, 20 /* ATIMWindowSize */,//end of JUNGMIN	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};/* ======================================================================   TCL Hooks for the simulator   ====================================================================== */static class Mac802_11Class : public TclClass {public:	Mac802_11Class() : TclClass("Mac/802_11") {}	TclObject* create(int, const char*const*) {		return (new Mac802_11(&PMIB, &MMIB));	}} class_mac802_11;/* ======================================================================   Mac Class Functions   ====================================================================== */Mac802_11::Mac802_11(PHY_MIB *p, MAC_MIB *m) : Mac(), mhIF_(this), mhNav_(this), mhRecv_(this), mhRecvDATA_(this), mhSend_(this), mhDefer_(this, p->SlotTime), mhBackoff_(this, p->SlotTime)//JUNGMIN	,mhBeacon_(this), mhBeaconBackoff_(this), mhATIMWindow_(this)	,mhWait_(this) //end of JUNGMIN{	macmib_ = m;	phymib_ = p;	nav_ = 0.0;//JUNGMIN	mhChannelUsage_ = new ChannelUsageTimer[NUMBER_OF_CHANNELS](this);	//initialize Free Channel List and Channel NAV	for(int i=0; i<NUMBER_OF_CHANNELS; i++) {				fcl_[i] = 0;		dca_cul_[i] = 0.0;		mhChannelUsage_[i].AssignChannel(i);	}	selected_channel_ = -1;	active_channel_ = 0;	ready_for_atim_ = 0;	next_beacon_time_ = 0;	recved_bytes_ = 0;	ResetDestInfo();//end of JUNGMIN	tx_state_ = rx_state_ = dx_state_ = MAC_IDLE;	tx_active_ = 0;		pktRTS_ = 0;	pktCTRL_ = 0;	pktRSH_ = 0;//JUNGMIN	pktATIM_ = 0;	pktATIMACK_ = 0;	pktATIMRSH_ = 0;	pktDx_	= 0;	pktPending_ = 0;//end of JUNGMIN	cw_ = phymib_->CWMin;	ssrc_ = slrc_ = 0;//JUNGMIN	sarc_ = 0;//end of JUNGMIN	packet_count_ = 0;	total_delay_ = 0.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) + difs_;		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;//JUNGMIN	pc_ = 0;	btbs_ = 0;	atim_window_ = 0;	dca_ = 0;//end of JUNGMIN		// chk if basic/data rates are set	// otherwise use bandwidth_ as default;		Tcl& tcl = Tcl::instance();	tcl.evalf("Mac/802_11 set basicRate_");	if (strcmp(tcl.result(), "0") != 0) 		bind_bw("basicRate_", &basicRate_);	else		basicRate_ = bandwidth_;	tcl.evalf("Mac/802_11 set dataRate_");	if (strcmp(tcl.result(), "0") != 0) 		bind_bw("dataRate_", &dataRate_);	else		dataRate_ = bandwidth_;	}intMac802_11::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;		}//JUNGMIN		//Sets the beacon period		  else if(strcmp(argv[1], "beaconperiod") == 0) {			macmib_->dot11BeaconPeriod = atoi(argv[2]);			return TCL_OK; 		} else if(strcmp(argv[1], "atimwindowsize") == 0) {			macmib_->dot11ATIMWindowSize = atoi(argv[2]);			return TCL_OK;		}	}	else if(argc == 2) {		//Let this node be the Point Coordinator 		if(strcmp(argv[1], "make-pc") == 0) {			pc_ = 1;			mhBeacon_.start(macmib_->dot11BeaconPeriod*0.001000);			next_beacon_time_ = NOW + (macmib_->dot11BeaconPeriod * 0.001000);				return TCL_OK;		} else if(strcmp(argv[1], "recved_bytes") == 0) {			printf("%d\n", recved_bytes_);			fflush(stdout);			return TCL_OK;		} else if(strcmp(argv[1], "average_delay") == 0) {			if(packet_count_ != 0) {				printf("%lf\n", (total_delay_ / (double)packet_count_));			} else {				printf("");			}			fflush(stdout);			return TCL_OK;		} else if(strcmp(argv[1], "dca") == 0) {			dca_ = 1;			return TCL_OK;		}//end of JUNGMIN	}		return Mac::command(argc, argv);}/* ======================================================================   Debugging Routines   ====================================================================== */voidMac802_11::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_11::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_11::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_11::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_11::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_11::is_idle(){	if(rx_state_ != MAC_IDLE)		return 0;	if(tx_state_ != MAC_IDLE)		return 0;	if(dx_state_ != MAC_IDLE)		return 0;	if(nav_ > Scheduler::instance().clock())		return 0;	return 1;}inline intMac802_11::is_channel_idle(int ch){	if(rx_state_ != MAC_IDLE)		return 0;	if(tx_state_ != MAC_IDLE)		return 0;	return 1;}voidMac802_11::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);		break;	case MAC_Type_Control:		switch(mh->dh_fc.fc_subtype) {		case MAC_Subtype_DRTS:		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_DCTS:		case MAC_Subtype_DRSH:		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_11::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_11::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);	}}//JUNGMIN	//When a node becomes available to transmit a packet, it checks whether	//there is a packet that needs to be sent.//end of JUNGMINvoidMac802_11::tx_resume(){	assert(mhSend_.busy() == 0);	assert(mhDefer_.busy() == 0);//JUNGMIN	if(btbs_) {		btbs_ = 0;		send_beacon();	}//end of JUNGMIN	//Shouldn't we use else if?	if(pktCTRL_) {		//printf("[%d] tx_resume(): Control Packet Ready.\n", index_); 		/*		 *  Need to send a CTS or ACK.		 */		mhDefer_.start(sifs_);	} //JUNGMIN	else if(pktATIMRSH_) {		mhDefer_.start(sifs_);	}	else if(pktATIMACK_) {		mhDefer_.start(sifs_);	}	else if(pktPCF_) {		if(mhBackoff_.busy()) {			mhBackoff_.stop();		}		mhDefer_.start(sifs_);	}	else if(pktATIM_) {		if(mhBackoff_.busy() == 0) 			mhDefer_.start(difs_);	}//end of JUNGMIN	else if(pktRTS_) { 		if(mhBackoff_.busy() == 0)			mhDefer_.start(difs_);	} else if(pktTx_) {

⌨️ 快捷键说明

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