📄 mac-802_11.c
字号:
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 + -