📄 mac-802_11e.cc
字号:
}voidMac802_11e::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); }}voidMac802_11e::tx_resume(){ double rTime; assert(mhSend_.busy() == 0); for(int pri = 0; pri < MAX_PRI; pri++){ //assert(mhDefer_.defer(pri) == 0); if(!mhDefer_.defer(pri)) { if(pktCTRL_[pri]) { /* * Need to send a CTS or ACK. */ mhSifs_.start(pri, sifs_); } else if(pktRTS_[pri]) { if(mhBackoff_.backoff(pri) == 0) { rTime = (Random::random() % getCW(LEVEL(pktRTS_[pri]))) * phymib_.getSlotTime(); mhDefer_.start(pri, getAIFS(LEVEL(pktRTS_[pri]))); } } else if(pktTx_[pri]) { if(mhBackoff_.backoff(pri) == 0) { hdr_cmn *ch = HDR_CMN(pktTx_[pri]); struct hdr_mac802_11e *mh = HDR_MAC802_11E(pktTx_[pri]); if ((u_int32_t) ch->size() < macmib_.RTSThreshold || (u_int32_t) ETHER_ADDR(mh->dh_da) == MAC_BROADCAST) { if((u_int32_t) ETHER_ADDR(mh->dh_da) == MAC_BROADCAST) rTime = (Random::random() % (getCW(pri) + 1)) * phymib_.getSlotTime(); else rTime = 0; mhDefer_.start(pri, getAIFS(pri) + rTime); } else { mhSifs_.start(pri, sifs_); } } } else if(callback_[pri] != 0) { rtx_[pri] = 0; Handler *h = callback_[pri]; callback_[pri] = 0; h->handle((Event*) 0); } set_tx_state(pri, MAC_IDLE); } }}voidMac802_11e::rx_resume(){ assert(pktRx_ == 0); assert(mhRecv_.busy() == 0); set_rx_state(MAC_IDLE);}/* ====================================================================== Timer Handler Routines ====================================================================== */voidMac802_11e::backoffHandler(int pri){ if(pktCTRL_[pri]) { assert(mhSend_.busy() || mhDefer_.defer(pri)); return; } if(check_pktRTS(pri) == 0) return; if(check_pktTx(pri) == 0) return;}voidMac802_11e::deferHandler(int pri){ assert(pktCTRL_[pri] || pktRTS_[pri] || pktTx_[pri]); if(check_pktCTRL(pri) == 0) return; assert(mhBackoff_.backoff(pri) == 0); //if (mhBackoff_.busy() != 0) //{ // printf("deferHandler:mhBackoff_ busy!\n"); // return; //} if(check_pktRTS(pri) == 0) return; if(check_pktTx(pri) == 0) return;}voidMac802_11e::navHandler(){ eifs_nav_ = 0.0; if(is_idle() && mhBackoff_.paused()) { mhBackoff_.resume(); }}voidMac802_11e::recvHandler(){ recv_timer();}voidMac802_11e::sendHandler(){ Scheduler &s = Scheduler::instance(); sending = 0; check_backoff_timer(); send_timer();}voidMac802_11e::txHandler(){ tx_active_ = 0; if(cfb_ && !cfb_broadcast) cfb_active = 0; if(cfb_broadcast) cfb_broadcast = 0;}voidMac802_11e::defer_stop(int pri){ mhBackoff_.start(pri, getCW(pri), is_idle());}/* sends the throughput every AK_INTERVAL to Akaroa * via AkObservation. This works only if you have * installed Akaroa and the ns-2/Akaroa interface. */voidMac802_11e::calc_throughput(){#if AKAROA > 0 if(AKAROA){ if(index_ > 0){ //int pri = 2; // jitter is for cases in which the simulation is // already in a steady state at the very beginning if (jitter >0) {if(jitter >= 10 ) jitter -= 10; } for(int pri = 0; pri < 3; pri++){ if(jitter > 0){ throughput = ((numbytes_[pri] * 8.) / interval_) + Random::uniform(0,jitter); }else { throughput = (8. * numbytes_[pri]) / interval_; } if(throughput <= 0) throughput = 0.0001; AkObservation((3 * (index_ - 1)) + (pri + 1), throughput); //AkObservation((6 * (index_ - 1)) + (pri + 1), throughput); //AkObservation((pri + 1), throughput); //AkObservation(1, throughput); //if(index_ == 1 && pri == 0) { cout.precision(16); //cout<<"Mac "<<index_<<", now: "<<Scheduler::instance().clock()<<", priority "<<pri<<", throughput: "<<throughput<<", interval_: "<<interval_<<" numbytes " << numbytes_[pri] <<" jitter "<<jitter<<"\n"; //} numbytes_[pri] = 0; throughput = 0; } AK.start(); } }#endif}/* ====================================================================== The "real" Timer Handler Routines ====================================================================== */voidMac802_11e::send_timer(){ Scheduler &s = Scheduler::instance(); for(int pri = 0; pri < MAX_PRI; pri ++){ switch(tx_state_[pri]) { /* * Sent a RTS, but did not receive a CTS. */ case MAC_RTS: RetransmitRTS(pri); break; /* * Sent a CTS, but did not receive a DATA packet. */ case MAC_CTS: assert(pktCTRL_[pri]); Packet::free(pktCTRL_[pri]); pktCTRL_[pri] = 0; break; /* * Sent DATA, but did not receive an ACK packet. */ case MAC_SEND: RetransmitDATA(pri); break; /* * Sent an ACK, and now ready to resume transmission. */ case MAC_ACK: assert(pktCTRL_[pri]); Packet::free(pktCTRL_[pri]); pktCTRL_[pri] = 0; break; case MAC_IDLE: break; default: assert(0); } } // if(mhDefer_.busy()) mhDefer_.stop(); if(!cfb_active) tx_resume(); }/* ====================================================================== Outgoing Packet Routines ====================================================================== */intMac802_11e::check_pktCTRL(int pri) { struct hdr_mac802_11e *mh; double timeout; if(pktCTRL_[pri] == 0) return -1; if(tx_state_[pri] == MAC_CTS || tx_state_[pri] == MAC_ACK) return -1; mh = HDR_MAC802_11E(pktCTRL_[pri]); 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_[pri], DROP_MAC_BUSY); pktCTRL_[pri] = 0; return 0; } set_tx_state(pri, MAC_CTS); /* * timeout: cts + data tx time calculated by * adding cts tx time to the cts duration * minus ack tx time -- this timeout is * a guess since it is unspecified * (note: mh->dh_duration == cf->cf_duration) */ timeout = txtime(phymib_.getCTSlen(), basicRate_) + DSSS_EDCA_MaxPropagationDelay // XXX + sec(mh->dh_duration) + DSSS_EDCA_MaxPropagationDelay // XXX - sifs_ - txtime(phymib_.getACKlen(), basicRate_); 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(pri, MAC_ACK); timeout = txtime(phymib_.getACKlen(), basicRate_); break; default: fprintf(stderr, "check_pktCTRL:Invalid MAC Control subtype\n"); exit(1); } transmit(pktCTRL_[pri], timeout); return 0;}intMac802_11e::check_pktRTS(int pri) { struct hdr_mac802_11e *mh; double timeout; assert(mhBackoff_.backoff(pri) == 0); if(pktRTS_[pri] == 0) return -1; //struct hdr_cmn *ch = HDR_CMN(pktRTS_); mh = HDR_MAC802_11E(pktRTS_[pri]); switch(mh->dh_fc.fc_subtype) { case MAC_Subtype_RTS: if(! is_idle()) { inc_cw(pri); mhBackoff_.start(pri, getCW(pri), is_idle()); return 0; } set_tx_state(pri, MAC_RTS); timeout = txtime(phymib_.getRTSlen(), basicRate_) + DSSS_EDCA_MaxPropagationDelay // XXX + sifs_ + txtime(phymib_.getCTSlen(), basicRate_) + DSSS_EDCA_MaxPropagationDelay; // XXX break; default: fprintf(stderr, "check_pktRTS:Invalid MAC Control subtype\n"); exit(1); } transmit(pktRTS_[pri], timeout); return 0;}int Mac802_11e::check_pktTx(int pri){ struct hdr_mac802_11e *mh; double timeout; assert(mhBackoff_.backoff(pri) == 0); if(pktTx_[pri] == 0) { return -1; } mh = HDR_MAC802_11E(pktTx_[pri]); //int len = HDR_CMN(pktTx_)->size(); switch(mh->dh_fc.fc_subtype) { case MAC_Subtype_Data: /*if(!is_idle()){ sendRTS(pri, ETHER_ADDR(mh->dh_da)); inc_cw(LEVEL(pktTx_[pri])); mhBackoff_.start(LEVEL(pktTx_[pri]), getCW(LEVEL(pktTx_[pri])), is_idle()); return 0; }*/ set_tx_state(pri, MAC_SEND); if((u_int32_t)ETHER_ADDR(mh->dh_da) != MAC_BROADCAST) timeout = txtime(pktTx_[pri]) + DSSS_EDCA_MaxPropagationDelay // XXX + sifs_ + txtime(phymib_.getACKlen(), basicRate_) + DSSS_EDCA_MaxPropagationDelay; // XXX else timeout = txtime(pktTx_[pri]); break; default: fprintf(stderr, "check_pktTx:Invalid MAC Control subtype\n"); //printf("pktRTS:%x, pktCTS/ACK:%x, pktTx:%x\n",pktRTS_, pktCTRL_,pktTx_); exit(1); } transmit(pktTx_[pri], timeout); return 0;}/* * Low-level transmit functions that actually place the packet onto * the channel. */voidMac802_11e::sendRTS(int pri, int dst){ Packet *p = Packet::alloc(); hdr_cmn* ch = HDR_CMN(p); struct rts_frame *rf = (struct rts_frame*)p->access(hdr_mac::offset_); assert(pktTx_[pri]); assert(pktRTS_[pri] == 0); /* * If the size of the packet is larger than the * RTSThreshold, then perform the RTS/CTS exchange. * * XXX: also skip if destination is a broadcast */ if( (u_int32_t) HDR_CMN(pktTx_[pri])->size() < macmib_.RTSThreshold || (u_int32_t) dst == MAC_BROADCAST) { Packet::free(p); //p = 0; return; } ch->uid() = 0; ch->ptype() = PT_MAC; ch->size() = phymib_.getRTSlen(); ch->iface() = -2; ch->error() = 0; bzero(rf, MAC_HDR_LEN); rf->rf_fc.fc_protocol_version = MAC_ProtocolVersion; rf->rf_fc.fc_type = MAC_Type_Control; rf->rf_fc.fc_subtype = MAC_Subtype_RTS; rf->rf_fc.fc_to_ds = 0; rf->rf_fc.fc_from_ds = 0; rf->rf_fc.fc_more_frag = 0; rf->rf_fc.fc_retry = 0; rf->rf_fc.fc_pwr_mgt = 0; rf->rf_fc.fc_more_data = 0; rf->rf_fc.fc_wep = 0; rf->rf_fc.fc_order = 0; //rf->rf_duration = RTS_DURATION(pktTx_); STORE4BYTE(&dst, (rf->rf_ra)); /* store rts tx time */ ch->txtime() = txtime(ch->size(), basicRate_); STORE4BYTE(&index_, (rf->rf_ta)); /* calculate rts duration field */ rf->rf_duration = usec(sifs_ + txtime(phymib_.getCTSlen(), basicRate_) + sifs_ + txtime(pktTx_[pri]) + sifs_ + txtime(phymib_.getACKlen(), basicRate_)); pktRTS_[pri] = p;}voidMac802_11e::sendCTS(int pri, int dst, double rts_duration){ Packet *p = Packet::alloc();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -