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

📄 mac-802_11.cc

📁 ns2.1b5版本中cbrp碼
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* mac-802_11.cc   $Id: mac-802_11.cc,v 1.19 1998/11/19 06:22:10 dmaltz Exp $   */#include <delay.h>#include <connector.h>#include <packet.h>#include <random.h>// #define DEBUG#include <cmu/debug.h>#include <cmu/arp.h>#include <cmu/ll.h> #include <cmu/mac.h>#include <cmu/mac-timers.h>#include <cmu/mac-802_11.h>#include <cmu/cmu-trace.h>/* ======================================================================   Macros   ====================================================================== */#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_MAC(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.                                      \         */                                                             \        sendtarget_->recv(p->copy(), this);                             \                                                                        \        mhSend.start(t);                                                \                                                                        \	mhIF.start(TX_Time(p));                                         \}#define SET_RX_STATE(x)			\{					\	rx_state = (x);			\					\	CHECK_BACKOFF_TIMER();		\}#define SET_TX_STATE(x)				\{						\	tx_state = (x);				\						\	CHECK_BACKOFF_TIMER();			\}/* ======================================================================   Global Variables   ====================================================================== */extern char* pt_names[];static PHY_MIB PMIB ={	DSSS_CWMin, DSSS_CWMax, DSSS_SlotTime, DSSS_CCATime,	DSSS_RxTxTurnaroundTime, DSSS_SIFSTime, DSSS_PreambleLength,	DSSS_PLCPHeaderLength};	static MAC_MIB MMIB ={	0 /* MAC_RTSThreshold */, MAC_ShortRetryLimit,	MAC_LongRetryLimit, MAC_FragmentationThreshold,	MAC_MaxTransmitMSDULifetime, MAC_MaxReceiveLifetime,	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), mhSend(this),	mhDefer(this, p->SlotTime), mhBackoff(this, p->SlotTime){	macmib = m;	phymib = p;	nav = 0.0;	tx_state = rx_state = MAC_IDLE;	tx_active = 0;	pktRTS = 0;	pktCTRL = 0;	cw = phymib->CWMin;	ssrc = slrc = 0;	sifs = phymib->SIFSTime;	pifs = sifs + phymib->SlotTime;	difs = sifs + 2*phymib->SlotTime;	eifs = sifs + difs + DATA_Time(ETHER_ACK_LEN +		phymib->PreambleLength/8 + phymib->PLCPHeaderLength/8);	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;}	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;		}		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;					}	}	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_MAC(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, pt_names[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, upcall: %x\n",		(int) pktTx, (int) pktRx, (int) pktRTS,		(int) pktCTRL, (int) upcall_);	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, u_int32_t dst){	struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr;	if(dst)		ETHER_ADDR(dh->dh_da) = dst;	return ETHER_ADDR(dh->dh_da);}inline int Mac802_11::hdr_src(char* hdr, u_int32_t src){	struct hdr_mac802_11 *dh = (struct hdr_mac802_11*) hdr;	if(src)		ETHER_ADDR(dh->dh_sa) = src;	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)	        SET_ETHER_TYPE(dh->dh_body, type);	return GET_ETHER_TYPE(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(nav > Scheduler::instance().clock())		return 0;	return 1;}voidMac802_11::discard(Packet *p, const char* why){	hdr_mac802_11* mh = HDR_MAC(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);		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);		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(ETHER_ADDR(mh->dh_sa) == index) {				drop(p, why);				return;			}		/* fall through - if necessary */		case MAC_Subtype_CTS:		case MAC_Subtype_ACK:			if(ETHER_ADDR(mh->dh_da) == 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(ETHER_ADDR(mh->dh_da) == index ||			   ETHER_ADDR(mh->dh_sa) == index ||			   ETHER_ADDR(mh->dh_da) == MAC_BROADCAST) {				drop(p, why);				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 + TX_Time(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(TX_Time(p) > mhRecv.expire()) {			mhRecv.stop();			discard(pktRx, DROP_MAC_COLLISION);			pktRx = p;			mhRecv.start(TX_Time(pktRx));		}		else {			discard(p, DROP_MAC_COLLISION);		}		break;	default:		assert(0);	}}voidMac802_11::tx_resume(){	assert(mhSend.busy() == 0);	assert(mhDefer.busy() == 0);	if(pktCTRL) {		/*		 *  Need to send a CTS or ACK.		 */		mhDefer.start(sifs);	}	else if(pktRTS) {		if(mhBackoff.busy() == 0)			mhDefer.start(difs);	}	else if(pktTx) {		if(mhBackoff.busy() == 0)			mhDefer.start(difs);	}	else if(upcall_) {		Handler *h = upcall_;		upcall_ = 0;		h->handle((Event*) 0);	}	SET_TX_STATE(MAC_IDLE);}voidMac802_11::rx_resume(){	assert(pktRx == 0);	assert(mhRecv.busy() == 0);	SET_RX_STATE(MAC_IDLE);}/* ======================================================================   Timer Handler Routines   ====================================================================== */voidMac802_11::backoffHandler(){	if(pktCTRL) {		assert(mhSend.busy() || mhDefer.busy());		return;	}	if(check_pktRTS() == 0)		return;	if(check_pktTx() == 0)		return;}voidMac802_11::deferHandler(){	assert(pktCTRL || pktRTS || pktTx);	if(check_pktCTRL() == 0)		return;	assert(mhBackoff.busy() == 0);	if(check_pktRTS() == 0)		return;	if(check_pktTx() == 0)		return;}voidMac802_11::navHandler(){	if(is_idle() && mhBackoff.paused())		mhBackoff.resume(difs);}voidMac802_11::recvHandler(){	recv_timer();}voidMac802_11::sendHandler(){	send_timer();}voidMac802_11::txHandler(){	tx_active = 0;}/* ======================================================================   The "real" Timer Handler Routines   ====================================================================== */voidMac802_11::send_timer(){	switch(tx_state) {	/*	 * Sent a RTS, but did not receive a CTS.	 */	case MAC_RTS:		RetransmitRTS();		break;	/*	 * Sent a CTS, but did not receive a DATA packet.	 */	case MAC_CTS:		assert(pktCTRL);		Packet::free(pktCTRL); pktCTRL = 0;		break;	/*	 * Sent DATA, but did not receive an ACK packet.	 */	case MAC_SEND:		RetransmitDATA();		break;			/*	 * Sent an ACK, and now ready to resume transmission.	 */	case MAC_ACK:		assert(pktCTRL);		Packet::free(pktCTRL); pktCTRL = 0;		break;	case MAC_IDLE:		break;	default:		assert(0);	}	tx_resume();}/* ======================================================================   Outgoing Packet Routines   ====================================================================== */intMac802_11::check_pktCTRL(){	struct hdr_mac802_11 *mh;	double timeout;	if(pktCTRL == 0)		return -1;	if(tx_state == MAC_CTS || tx_state == MAC_ACK)		return -1;	mh = HDR_MAC(pktCTRL);	switch(mh->dh_fc.fc_subtype) {	/*	 *  If the medium is not IDLE, don't send the CTS.	 */	case MAC_Subtype_CTS:		if(! is_idle()) {			discard(pktCTRL, DROP_MAC_BUSY); pktCTRL = 0;			return 0;		}		SET_TX_STATE(MAC_CTS);		timeout = (mh->dh_duration * 1e-6) + CTS_Time; // XXX		break;	/*	 * IEEE 802.11 specs, section 9.2.8	 * Acknowledments are sent after an SIFS, without regard to	 * the busy/idle state of the medium.	 */	case MAC_Subtype_ACK:		SET_TX_STATE(MAC_ACK);		timeout = ACK_Time;		break;	default:		fprintf(stderr, "Invalid MAC Control subtype\n");		exit(1);	}        TRANSMIT(pktCTRL, timeout);	return 0;}intMac802_11::check_pktRTS(){	struct hdr_mac802_11 *mh;	double timeout;	assert(mhBackoff.busy() == 0);	if(pktRTS == 0)		return -1;	mh = HDR_MAC(pktRTS);	switch(mh->dh_fc.fc_subtype) {	case MAC_Subtype_RTS:		if(! is_idle()) {			inc_cw();			mhBackoff.start(cw, is_idle());			return 0;		}		SET_TX_STATE(MAC_RTS);		timeout = CTSTimeout;		break;	default:		fprintf(stderr, "Invalid MAC Control subtype\n");		exit(1);	}        TRANSMIT(pktRTS, timeout);	return 0;}intMac802_11::check_pktTx(){	struct hdr_mac802_11 *mh;	double timeout;	assert(mhBackoff.busy() == 0);	if(pktTx == 0)		return -1;	mh = HDR_MAC(pktTx);       	int len = HDR_CMN(pktTx)->size();	switch(mh->dh_fc.fc_subtype) {	case MAC_Subtype_Data:		if(! is_idle()) {			sendRTS(ETHER_ADDR(mh->dh_da));			inc_cw();			mhBackoff.start(cw, is_idle());			return 0;		}		SET_TX_STATE(MAC_SEND);		if(ETHER_ADDR(mh->dh_da) != MAC_BROADCAST)			timeout = ACKTimeout(len);		else			timeout = TX_Time(pktTx);		break;	default:		fprintf(stderr, "Invalid MAC Control subtype\n");		exit(1);	}

⌨️ 快捷键说明

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