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

📄 mac-802_11.cc

📁 ns2 中802.11 mac层的实现代码!
💻 CC
📖 第 1 页 / 共 4 页
字号:
			else {				discard(p, DROP_MAC_BUSY);				//printf("(%d)..discard DATA\n",index_);				return;			}			sendACK(src);			tx_resume();		}		/*		 *  We did not send a CTS and there's no		 *  room to buffer an ACK.		 */		else {			if(pktCTRL_) {				discard(p, DROP_MAC_BUSY);				return;			}			sendACK(src);			if(mhSend_.busy() == 0)				tx_resume();		}	}	/* ============================================================	    Make/update an entry in our sequence number cache.	   ============================================================ */	/* Changed by Debojyoti Dutta. This upper loop of if{}else was 	   suggested by Joerg Diederich <dieder@ibr.cs.tu-bs.de>. 	   Changed on 19th Oct'2000 */        if(dst != MAC_BROADCAST) {                if (src < (u_int32_t) cache_node_count_) {                        Host *h = &cache_[src];                        if(h->seqno && h->seqno == dh->dh_scontrol) {                                discard(p, DROP_MAC_DUPLICATE);                                return;                        }                        h->seqno = dh->dh_scontrol;                } else {			static int count = 0;			if (++count <= 10) {				printf ("MAC_802_11: accessing MAC cache_ array out of range (src %u, dst %u, size %d)!\n", src, dst, cache_node_count_);				if (count == 10)					printf ("[suppressing additional MAC cache_ warnings]\n");			};		};	}	/*	 *  Pass the packet up to the link-layer.	 *  XXX - we could schedule an event to account	 *  for this processing delay.	 */	p->incoming = 1;	uptarget_->recv(p, (Handler*) 0);}voidMac802_11::recvACK(Packet *p){		struct hdr_cmn *ch = HDR_CMN(p);	if(tx_state_ != MAC_SEND) {	discard(p, DROP_MAC_INVALID_STATE);	return;	}	//printf("(%d)...................recving ACK:%x\n",index_,p);	assert(pktTx_);	Packet::free(pktTx_); pktTx_ = 0;	mhSend_.stop();	/*	 * The successful reception of this ACK packet implies	 * that our DATA transmission was successful.  Hence,	 * we can reset the Short/Long Retry Count and the CW.	 */	if((u_int32_t) ch->size() <= macmib_->RTSThreshold)		ssrc_ = 0;	else		slrc_ = 0;	/*	 * Backoff before sending again.	 */	rst_cw();	assert(mhBackoff_.busy() == 0);	mhBackoff_.start(cw_, is_idle());	tx_resume();	mac_log(p);}// wqos - Wed 29 Nov 00, 13:20 - dugdalevoidMac802_11::recvPoll(Packet *p) {	Packet *tp;	//      tp = ll_->ifq()->deque();	//      tp = ((Queue *)((LL *)uptarget_)->downtarget())->deque();	mac_log(p);	//  rx_resume();	// Hmmm... maybe not so good...	//	if(mhBackoff_.busy() && !mhBackoff_.paused())	if(mhBackoff_.busy())		mhBackoff_.stop();	//		mhBackoff_.pause(); retryPoll:	if(!pktTx_) {  		// Unless there already is a packet to be sent, try to dequeuec one		tp = ((Queue *)(ll_->downtarget()))->deque();		if(tp) { // Did we get a packet from the queue?			//	abort();			//send(tp, 0);			//if(!pollsToSend_)			//pollsToSend_=1;			trace_pkt(tp);			// Try with this commented out!!!			// It is NOT good that the stuff below is here, but for some strange			// reason it won't work without it... Not really correct, but it			// works until I find out what's wrong.			if(HDR_CMN(tp)->ptype()==PT_ARP||HDR_CMN(tp)->ptype()==PT_MESSAGE) {				Packet::free(tp); tp=0;				goto retryPoll;			}			sendDATA(tp);						fprintf(stderr, "Hej %x %x %d %d!\n", ((struct hdr_mac802_11 *)pktTx_)->dh_fc.fc_type,((struct hdr_mac802_11 *)pktTx_)->dh_fc.fc_subtype,((struct hdr_mac802_11 *)HDR_MAC802_11(pktTx_))->dh_scontrol, pktTx_==0);									((struct hdr_mac802_11 *)HDR_MAC802_11(pktTx_))->dh_scontrol = sta_seqno_++;			((struct hdr_mac802_11 *)HDR_MAC802_11(pktTx_))->dh_duration = 32768;		}	} else {		trace_pkt(pktTx_);		if(HDR_CMN(pktTx_)->ptype()==PT_ARP||HDR_CMN(pktTx_)->ptype()==PT_MESSAGE) {			Packet::free(pktTx_); pktTx_=0;			goto retryPoll;		}				//if(!pollsToSend_)		//pollsToSend_=1;		fprintf(stderr,"tx_state_:%x %d\n",tx_state_,cfp_);		((struct hdr_mac802_11 *)HDR_MAC802_11(pktTx_))->dh_duration = 32768;				if(pktRTS_) {			// We won't be needing this RTS frame			Packet::free(pktRTS_); pktRTS_=0; 		}			}	if(!mhDefer_.busy()&&pktTx_)		mhDefer_.start(sifs_);		// If there is no packet to send in the queue, the station won't do anything, so a	// timer will time out at the PC, and a new poll frame will be sent (to another station)	// Would be better if this station sent a "No data" frame in this case.	// Not implemented yet.}// wqos - changes by dugdale ends// wqos - Mon 09 Oct 00, 20:01 - dugdale voidMac802_11::do_cfp(){	// Hmmm... Not much use having this function	sendPoll();}voidMac802_11::send_beacon(){	if(tx_state_!=MAC_SEND&&tx_state_!=MAC_CTS && rx_state_==MAC_IDLE) {		// We can send the beacon now		pcfSend(MAC_Type_Management, MAC_Subtype_Beacon);	} else {		// We have to wait to send the beacon, but set the flag		// (btbs=beacon to be sent) so we know that it should be sent.		btbs_=1;	}}voidMac802_11::sendPoll(){	pcfSend(MAC_Type_Data, MAC_Subtype_CFPoll);}voidMac802_11::sendCFEnd(){	pcfSend(MAC_Type_Control, MAC_Subtype_CFEnd);}// wqos - changes by dugdale ends// wqos - Tue 24 Oct 00, 10:20 - dugdale/*	Function to send the control frames of the PCF mode.	The frame sent depends on the arguments to the function.	Called by send_beacon(), sendPoll(), and sendCFEnd(). */voidMac802_11::pcfSend(int type, int subtype){	Packet* p = Packet::alloc();	struct hdr_mac802_11 *mh =  (struct hdr_mac802_11 *)p->access(hdr_mac::offset_);	hdr_cmn* ch = HDR_CMN(p);	ch->ptype()=PT_MAC;	int dst = MAC_BROADCAST;	double defertime=pifs_;	Scheduler &s = Scheduler::instance();    	bzero(&mh->dh_fc, sizeof(struct frame_control));	// Set some info in the frame	mh->dh_fc.fc_protocol_version = MAC_ProtocolVersion;	mh->dh_fc.fc_type       = type;	mh->dh_fc.fc_subtype    = subtype;	/*	 * Assign the data packet a sequence number.	 */	mh->dh_scontrol = sta_seqno_++;	ch->size() += ETHER_HDR_LEN;  	switch(type) {	case MAC_Type_Management:		switch(subtype) {		case MAC_Subtype_Beacon:			struct beacon_frame *beacon = (struct beacon_frame *)p->access(hdr_mac::offset_);			// Schedule the transmission of the next beacon			// Moved to beaconHandler()			//			mhBeacon_.start(macmib_->dot11BeaconPeriod*0.001024);      			// do some timestamp stuff, and set it in the frame			beacon->bf_timestamp=(unsigned long long)((Scheduler::instance()).clock()*1000);      			// Set the beacon interval in the frame			beacon->bf_binterval=macmib_->dot11BeaconPeriod;            			//     assert(pktPCF_ == 0);			fprintf(stderr, "Beacon sent at %f\n", Scheduler::instance().clock());      			// set the TIM stuff			beacon->bf_tim.elemID       = MMFF_TIM;			beacon->bf_tim.length       = 6;			beacon->bf_tim.DTIMcount    = dtimcount_;			beacon->bf_tim.DTIMperiod   = macmib_->dot11DTIMPeriod;      			beacon->bf_cfparamset.CFPCount  = cfpcount_;			beacon->bf_cfparamset.CFPPeriod = macmib_->dot11CFPPeriod;			beacon->bf_cfparamset.CFPMaxDuration = macmib_->dot11CFPMaxDuration;      			beacon->bf_duration = 0;			if(dtimcount_==0) {				// We have a DTIM, and might want to start a CFP				dtimcount_=macmib_->dot11DTIMPeriod;				cfpcount_--;				beacon->bf_cfparamset.CFPCount  = cfpcount_;				if(cfpcount_ == 0) { // Let's do a CFP					//					cfp_ = 1; // CFP...					cfpcount_ = macmib_->dot11CFPPeriod;					// Calculate how many polls to send					pollsToSend_=pollList_->numPollable()-1;					// Calculate when the CFP must be over					lastPoll_=s.clock()+tutos(macmib_->dot11CFPMaxDuration) - 2346/bandwidth_;				}			} else {				dtimcount_--;			}			//     SET_TX_STATE(MAC_BEACONING); // HMMM...      			break;		}		break;	case MAC_Type_Control:		switch(subtype) {		case MAC_Subtype_CFEnd:			fprintf(stderr,"CFEnd: %f\n",s.clock());			//      assert(pktPCF_ == 0);            			mh->dh_duration = 32768;			//			mh->dh_scontrol = sta_seqno_++;      			cfp_ = 0;      			break;		}		break;	case MAC_Type_Data:		switch(subtype) {		case MAC_Subtype_CFPoll:			dst=pollList_->getNextPollable();			defertime=sifs_;			if(dst==-1) { // No stations to poll...				sendCFEnd(); 				return;			}			fprintf(stderr,"Poll: %d %f\n",dst,s.clock());			//     assert(pktPCF_ == 0);      			mh->dh_duration = 32768; // This is sent during a CFP      			mh->dh_scontrol = sta_seqno_++;			break;		}		break;	}	pktPCF_ = p;	STORE4BYTE(&dst,(mh->dh_da));	STORE4BYTE(&index_, (mh->dh_sa));	/* CAN THIS BE REMOVED?????? /dugdale	 * drop the packet if the node is in sleep mode	 XXX sleep mode can't stop node from sending packets	*/	EnergyModel *em = netif_->node()->energy_model();	if (em && em->sleep()) {		em->set_node_sleep(0);		em->set_node_state(EnergyModel::INROUTE);	}	if(mhBackoff_.busy() == 0) {		if(is_idle()) {			/*			 * If we are already deferring, there is no			 * need to reset the Defer timer.			 */			if(mhDefer_.busy() == 0)				mhDefer_.start(defertime);		}				/*		 * If the medium is NOT IDLE, then we start		 * the backoff timer.		 */		// Should we really do this here????????? /dugdale		else {			mhBackoff_.start(cw_, is_idle());		}	}}// wqos - changes by dugdale ends// wqos - Fri 06 Oct 00, 11:20 - almquist/* ======================================================================   Implementation of the PCFPollList    ======================================================================	 This polling list is used by the Point Coordinator (PC) in the PCF scheme	 to maintain a list of stations to poll (and of those not to poll as well).	 *//**	 Constructor	 This will initialize the list and set nextToBePolled to the first element in the list. */PCFPollList::PCFPollList(){	lastPollable = lastPolled = firstElement = lastElement = NULL;  // nrOfNodes = 0;  fprintf(stderr, "DEBUG: PCFPollList created\n");}/**	 Destructor	 This removes all elements in the poll list.*/PCFPollList::~PCFPollList(){  PCFPollElement *elem = firstElement;	PCFPollElement *tmpElem;	firstElement = lastElement = NULL;  fprintf(stderr, "DEBUG: PCFPollList: Deleting elements with macId_ : ");  while(elem != NULL){				tmpElem = elem;		elem = elem->next_;		fprintf(stderr, "%d, ", elem->macId_);    delete tmpElem;			}  fprintf(stderr, "\nDEBUG: PCFPollList destroyed\n");}/**	 This will return the macId of the node to be polled.	 	 @return The macId of the node to be polled or -1 if no nodes in list */intPCFPollList::getNextPollable(){  PCFPollElement *toBePolled;  if(firstElement == NULL){    return -1;  }  if(lastPolled == NULL || lastPolled == lastElement){    toBePolled = firstElement;  } else {    toBePolled = lastPolled->next_;  }	  switch(toBePolled->cfPollField_){  case 0: // STA is not pollable  case 1: // STA pollable but not req. to be put on pollinglist	case 3: // STA pollable but req. never to be polled (PowerSave)		if(toBePolled == lastElement){			return -1;		} else {			return(this->getNextPollable());		}    break;	case 2: // STA pollable and in pollinglist    if(toBePolled->dontPoll_){      return(this->getNextPollable());    }    lastPollable = toBePolled;    break;  default:    fprintf(stderr, "Error: PCFPollList getNextPollable(): node %d has invalid CFPollable+CFPollReq fields, %x !\n", toBePolled->macId_, toBePolled->cfPollField_);    break;  }  lastPolled = toBePolled;  return toBePolled->macId_;}/**	 This inserts an element last in the poll list.	 @param macId        The mac id of the node to insert.	 @param cfPollable   Indicates if this node is pollable (1 or 0)	 @param cfPollReq    Indicates if this node should be polled (1 or 0) */voidPCFPollList::insertNode(int macId, int cfPollable, int cfPollReq){  int cfPollField = (cfPollable<<1) | cfPollReq;  fprintf(stderr, "DEBUG: PCFPollList insertNode(%d, %d, %d): cfPollField = %d\n",	  macId, cfPollable, cfPollReq, cfPollField);  PCFPollElement *elem = new PCFPollElement(macId, cfPollField);  if(firstElement == NULL){    firstElement = lastElement = elem;  } else {    lastElement->next_ = elem;    lastElement = elem;  }  // nrOfNodes++;}/**   Deletes a node from the list   Returns zero if successful, otherwise -1*/intPCFPollList::deleteNode(int macId) {  PCFPollElement *prev=NULL, *elem = firstElement;  while(elem != NULL){    if(elem->macId_==macId) { // Remove this node from the list      if(prev)	prev->next_ = elem->next_;      else	firstElement = elem->next_;      if(!elem->next_) {	lastElement = prev;	prev->next_=NULL;      }      if(elem==lastPolled)	lastPolled=NULL;      delete(elem);      return 0;    }    prev=elem;    elem = elem->next_;  }  return -1;}/**   Initializes the list.*/voidPCFPollList::initPoll(){  lastPolled = NULL;  clearDontPoll();}/**   Used to perform some sort of polling policy.      @param macId if this is -1 disable last polled STA*/voidPCFPollList::markDontPoll(int macId){  if(macId != -1){    PCFPollElement *elem = firstElement;    while(elem != NULL && elem->macId_ != macId){      elem = elem->next_;    }    elem->dontPoll_ = 1;  } else {    lastPolled->dontPoll_ = 1;  }}/**	 Clears the dontPoll_ flag in all pollable nodes. */voidPCFPollList::clearDontPoll(){  PCFPollElement *elem = firstElement;  while(elem != NULL){    elem->dontPoll_ = 0;    elem = elem->next_;  }}/**       Returns the number of pollable stations */intPCFPollList::numPollable() {  PCFPollElement *elem = firstElement;  int num=0;  while(elem) {    if(elem->cfPollField_ == 2)      num++;    elem = elem->next_;  }  return num;}// wqos - changes by almquist ends

⌨️ 快捷键说明

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