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

📄 mac-802_3.cc

📁 ns2.1b5版本中cbrp碼
💻 CC
字号:
/*    mac-802_3.cc   $Id: mac-802_3.cc,v 1.6 1998/11/19 06:22:11 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-802_3.h>/* ======================================================================   TCL hooks for the 802.3 class.   ====================================================================== */static class Mac802_3Class : public TclClass {public:	Mac802_3Class() : TclClass("Mac/802_3") {}	TclObject* create(int, const char*const*) {		return (new Mac802_3);	}} class_mac802_3;/* ======================================================================   Defer Handler Functions	- used to resume the upper layer   ====================================================================== */voidMacHandlerDefer::handle(Event *){	busy_ = 0;	callback->handle((Event*) 0);}voidMacHandlerDefer::schedule(Handler *h, double t){	Scheduler& s = Scheduler::instance();	assert(h && busy_ == 0);	s.schedule(this, &intr, t);	busy_ = 1;	callback = h;}/* ======================================================================   Send Handler Functions	- called when a transmission completes without any collisions   ====================================================================== */voidMacHandlerSend::handle(Event*){	busy_ = 0;	/*	 *  Transmission completed successfully	 */	assert(mac->pktTx);	Packet::free(mac->pktTx);	mac->pktTx = 0;	mac->pktTxcnt = 0;	mac->resume();}voidMacHandlerSend::schedule(double t){	Scheduler& s = Scheduler::instance();	assert(busy_ == 0);	s.schedule(this, &intr, t);	busy_ = 1;}/* ======================================================================   Backoff Handler Functions   ====================================================================== */voidMacHandlerBack::handle(Event* e){	busy_ = 0;	mac->send((Packet*) e);}voidMacHandlerBack::schedule(Packet *p, double t) {	Scheduler& s = Scheduler::instance();	assert(p && busy_ == 0);	s.schedule(this, p, t);	busy_ = 1;}/* ======================================================================   Receive Handler Functions   ====================================================================== */voidMacHandlerRecv::handle(Event* e){	busy_ = 0;	/*	 * Reception Successful	 */	mac->pktRx = 0;	mac->recv_complete((Packet*) e);}voidMacHandlerRecv::schedule(Packet *p, double t) {	Scheduler& s = Scheduler::instance();	assert(p && busy_ == 0);	s.schedule(this, p, t);	busy_ = 1;	p_ = p;}/* ======================================================================   Packet Headers Routines   ====================================================================== */inline intMac802_3::hdr_dst(char* hdr, u_int32_t dst){	struct hdr_mac802_3 *mh = (struct hdr_mac802_3*) hdr;	if(dst)		ETHER_ADDR(mh->mh_da) = dst;	return ETHER_ADDR(mh->mh_da);}inline int Mac802_3::hdr_src(char* hdr, u_int32_t src){	struct hdr_mac802_3 *mh = (struct hdr_mac802_3*) hdr;	if(src)		ETHER_ADDR(mh->mh_sa) = src;	return ETHER_ADDR(mh->mh_sa);}inline int Mac802_3::hdr_type(char* hdr, u_int16_t type){	struct hdr_mac802_3 *mh = (struct hdr_mac802_3*) hdr;	if(type)		mh->mh_type = type;	return  mh->mh_type;}/* ======================================================================   Mac Class Functions   ====================================================================== */Mac802_3::Mac802_3() : Mac(), mhBack(this),mhDefer(this), mhRecv(this), mhSend(this){        pktTxcnt = 0;}intMac802_3::command(int argc, const char*const* argv){	return Mac::command(argc, argv);}void Mac802_3::discard(Packet *p, const char*){	hdr_mac802_3* mh = (hdr_mac802_3*)p->access(off_mac_);	if(ETHER_ADDR(mh->mh_da) == index)		drop(p);	else		Packet::free(p);}voidMac802_3::collision(Packet *p){	switch(state) {	case MAC_SEND:		assert(pktTx);		/*		 *  Collisions occur at the receiver, so receiving a		 *  packet, while transmitting may not be a problem.		 *		 *  If the packet is for us, then drop() the packet -		 *  ie; log an event recording the collision.		 *  Otherwise, just free the packet and forget about		 *  it.		 */		discard(p);		break;	case MAC_RECV:		assert(pktRx);		/*		 * Drop the packet that is presently being received.		 * Again, if the packet was not for us, then its not		 * really worth logging.		 */		mhRecv.cancel();		discard(pktRx);		pktRx = 0;		/*		 *  If the packet is for us, then drop() the packet -		 *  ie; log an event recording the collision.		 *  Otherwise, just free the packet and forget about		 *  it.		 */		discard(p);		resume();		// restart the MAC		break;	default:	  assert("SHOULD NEVER HAPPEN" == 0);	}}voidMac802_3::send(Packet *p, Handler *h){	hdr_cmn *hdr = HDR_CMN(p);	hdr->size() += ETHER_HDR_LEN;	upcall_ = h;	send(p);}/* * This function gets called when packets are passed down from the * link layer. */voidMac802_3::recv(Packet *p, Handler *h){	/*	 * Sanity Check	 */	assert(initialized());	/*	 *  Handle outgoing packets.	 */	if(h) {		send(p, h);		return;	}	/*	 *  Handle incoming packets.	 *	 *  We just received the 1st bit of a packet on the network	 *  interface.	 *	 */	if(state == MAC_IDLE) {		state = MAC_RECV;		pktRx = p;		/*		 * Schedule the reception of this packet, in		 * txtime seconds.		 */		mhRecv.schedule(p, netif_->txtime(p));#if 0		/*		 *  If we are in the first 2/3 of an IFS, then go		 *  ahead and cancel the timer.		 */		if(mhDefer.busy()) {			double now = Scheduler::instance().clock();			if(mhDefer.expire() - now > (IEEE_8023_IFS/3) ) {				mhDefer.cancel();			}			mhDefer.cancel();		}#endif	}	else {		collision(p);	}}voidMac802_3::send(Packet *p){	double txtime = netif_->txtime(p);	/*	 *  Sanity Check	 */	if(pktTx) {		drop(pktTx);		drop(p);		fprintf(stderr, "index: %d\n", index);		fprintf(stderr, "Backoff Timer: %d\n", mhBack.busy());		fprintf(stderr, "Defer Timer: %d\n", mhDefer.busy());		fprintf(stderr, "Recv Timer: %d\n", mhRecv.busy());		fprintf(stderr, "Send Timer: %d\n", mhSend.busy());		exit(1);	}	assert(upcall_ && pktTx == 0);	pktTx = p;	/*	 *  Perform carrier sense.  If the medium is not IDLE, then	 *  backoff again.  Otherwise, go for it!	 */	if(state != MAC_IDLE) {		backoff();		return;	}	state = MAC_SEND;	/*	 * 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);	/*	 * This MAC will remain in the MAC_SEND state until packet	 * transmission completes.  Schedule an event that will	 * reset the MAC to the IDLE state.	 */	mhSend.schedule(txtime);}voidMac802_3::recv_complete(Packet *p){	hdr_cmn *hdr = HDR_CMN(p);	hdr_mac802_3* mh = (hdr_mac802_3*)p->access(off_mac_);	/*	 * Address Filtering	 */	if(ETHER_ADDR(mh->mh_da) != (u_int32_t) index &&	   ETHER_ADDR(mh->mh_da) != MAC_BROADCAST) {		/*		 *  We don't want to log this event, so we just free		 *  the packet instead of calling the drop routine.		 */		Packet::free(p);		goto done;	}	/*	 * Now, check to see if this packet was received with enough	 * bit errors that the current level of FEC still could not	 * fix all of the problems - ie; after FEC, the checksum still	 * failed.	 */	if( hdr->error() ) {		discard(p);		goto done;	}	/*	 * Adjust the MAC packet size - ie; strip off the mac header	 */	hdr->size() -= ETHER_HDR_LEN;	/*	 *  Pass the packet up to the link-layer.	 *  XXX - we could schedule an event to account	 *  for this processing delay.	 */	recvtarget_->recv(p, (Handler*) 0);	done:	/*	 * reset the MAC to the IDLE state	 */	resume();}voidMac802_3::backoff() {	int k, r;	pktTxcnt++;	k = min(pktTxcnt, IEEE_8023_BLIMIT);	r = Random::integer(1 << k);	if(pktTxcnt < IEEE_8023_ALIMIT) {		mhBack.schedule(pktTx, r * IEEE_8023_SLOT);		pktTx = 0;		return;	}	else {		drop(pktTx);		pktTx = 0;		pktTxcnt = 0;	}}voidMac802_3::resume(){	state = MAC_IDLE;	/*	 *  Sanity Check	 */	assert(pktRx == 0);	assert(pktTx == 0);	// assert(mhDefer.busy() == 0);	assert(mhRecv.busy() == 0);	assert(mhSend.busy() == 0);	/*	 *  If we're not backing off right now, go ahead and unblock	 *  the upper layer so that we can get more packets to send.	 */	if(upcall_ && mhBack.busy() == 0) {		mhDefer.schedule(upcall_, IEEE_8023_IFS);		upcall_ = 0;	}}

⌨️ 快捷键说明

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