540 likes | 571 Views
Learn how RTS/CTS, NAV, and back-off timers are implemented in ns-2 for better wireless communication. Understand the packet sending process and frame structure in MAC layer.
E N D
NS2 HW3 2006/9/20 雷喻翔
Today’s Outline • How is the RTS/CTS implemented? • Is the default setting for RTS/CTS on or off in ns-2? • How is the NAV implemented? • How is the back-off timer implemented?
Today’s Outline • How is the RTS/CTS implemented? • Is the default setting for RTS/CTS on or off in ns-2? • How is the NAV implemented? • How is the back-off timer implemented?
DCF Four-way Two-way sender receiver sender receiver DIFS DIFS RTS data SIFS SIFS CTS ACK SIFS data SIFS ACK
How is the RTS/CTS implemented? • Sending a packet (no errors) recv() -> send() -> sendDATA() and sendRTS() -> start defer timer -> deferHandler() -> check_pktRTS() -> transmit() -> recv() -> receive timer started -> recv_timer() -> recvCTS() -> tx_resume() -> start defer timer -> rx_resume() -> deferHandler() -> check_pktTx() -> transmit() -> recv() -> receive timer started -> recv_timer() -> recvACK() -> tx_resume() -> callback_ -> rx_resume() -> done! receiver
recv() void Mac802_11::recv(Packet *p, Handler *h) { struct hdr_cmn *hdr = HDR_CMN(p); assert(initialized()); if( hdr->direction() == hdr_cmn::DOWN ) { send(p, h); return; } if(tx_active_ && hdr->error() == 0) { hdr->error() = 1; } if(rx_state_ == MAC_IDLE) { setRxState(MAC_RECV); pktRx_ = p; mhRecv_.start(txtime(p)); } else { ……………………………………………………………………………………… } } receiver
send() void Mac802_11::send(Packet *p, Handler *h) { double rTime; struct hdr_mac802_11* dh = HDR_MAC802_11(p); EnergyModel *em = netif_->node()->energy_model(); if (em && em->sleep()) { em->set_node_sleep(0); em->set_node_state(EnergyModel::INROUTE); } callback_ = h; sendDATA(p); sendRTS(ETHER_ADDR(dh->dh_ra)); dh->dh_scontrol = sta_seqno_++; if(mhBackoff_.busy() == 0) { if(is_idle()) { if (mhDefer_.busy() == 0) { rTime = (Random::random() % cw_) * (phymib_.getSlotTime()); mhDefer_.start(phymib_.getDIFS() + rTime); } } else { mhBackoff_.start(cw_, is_idle()); } } } main
Mac802_11::sendDATA(Packet *p) { hdr_cmn* ch = HDR_CMN(p); struct hdr_mac802_11* dh = HDR_MAC802_11(p); assert(pktTx_ == 0); ch->size() += phymib_.getHdrLen11(); dh->dh_fc.fc_protocol_version = MAC_ProtocolVersion; dh->dh_fc.fc_type = MAC_Type_Data; dh->dh_fc.fc_subtype = MAC_Subtype_Data; dh->dh_fc.fc_to_ds = 0; dh->dh_fc.fc_from_ds = 0; dh->dh_fc.fc_more_frag = 0; dh->dh_fc.fc_retry = 0; dh->dh_fc.fc_pwr_mgt = 0; dh->dh_fc.fc_more_data = 0; dh->dh_fc.fc_wep = 0; dh->dh_fc.fc_order = 0; /* store data tx time */ ch->txtime() = txtime(ch->size(), dataRate_); if((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) { /* store data tx time for unicast packets */ ch->txtime() = txtime(ch->size(), dataRate_); dh->dh_duration = usec(txtime(phymib_.getACKlen(), basicRate_) + phymib_.getSIFS()); } else { /* store data tx time for broadcast packets */ ch->txtime() = txtime(ch->size(), basicRate_ ); dh->dh_duration = 0; } pktTx_ = p; } sendDATA()
getHdrLen11() inline u_int32_t getHdrLen11(){ return (getPLCPhdrLen() + sizeof(struct hdr_mac802_11) + ETHER_FCS_LEN); }
void Mac802_11::sendRTS(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_); assert(pktRTS_ == 0); if( (u_int32_t) HDR_CMN(pktTx_) ->size() < macmib_.getRTSThreshold() || (u_int32_t) dst == MAC_BROADCAST) { Packet::free(p); 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; STORE4BYTE(&dst, (rf->rf_ra)); ch->txtime() = txtime(ch->size(), basicRate_ ); STORE4BYTE(&index_, (rf->rf_ta)); rf->rf_duration = usec(phymib_.getSIFS() + txtime(phymib_.getCTSlen(), basicRate_) + phymib_.getSIFS()+ txtime(pktTx_) + phymib_.getSIFS() + txtime(phymib_.getACKlen(), basicRate_)); pktRTS_ = p; } sendRTS() send RTSheader
deferHandler() void Mac802_11::deferHandler() { … if( check_pktCTRL() == 0) return; if( check_pktRTS() == 0) return; if( check_pktTx() == 0) return; }
check_pktRTS() int Mac802_11::check_pktRTS() { struct hdr_mac802_11 *mh; double timeout; if(pktRTS_ == 0) return -1; mh = HDR_MAC802_11(pktRTS_); switch(mh->dh_fc.fc_subtype) { case MAC_Subtype_RTS: if(! is_idle()) { inc_cw(); mhBackoff_.start(cw_, is_idle()); return 0; } setTxState(MAC_RTS); timeout = txtime(phymib_.getRTSlen(), basicRate_) + DSSS_MaxPropagationDelay + phymib_.getSIFS()+ txtime(phymib_.getCTSlen(), basicRate_)+ DSSS_MaxPropagationDelay; break; default: fprintf(stderr, "check_pktRTS:Invalid MAC Control subtype\n"); exit(1); } transmit(pktRTS_, timeout); return 0; }
transmit() inline voidMac802_11::transmit(Packet *p, double timeout){ tx_active_ = 1; … if(rx_state_ != MAC_IDLE) { assert(pktRx_); struct hdr_cmn *ch = HDR_CMN(pktRx_); ch->error() = 1; /* force packet discard */ } downtarget_->recv(p->copy(), this); mhSend_.start(timeout); mhIF_.start(txtime(p)); }
When mhIF_ timer expires void Mac802_11::txHandler() { if (EOTtarget_) { assert(eotPacket_); EOTtarget_->recv(eotPacket_, (Handler *) 0); eotPacket_ = NULL; } tx_active_ = 0; } main receiver
Void Mac802_11::recv_timer() { …………………. switch(type) { case MAC_Type_Management: ……………………………………… goto done; case MAC_Type_Control: switch(subtype) { case MAC_Subtype_RTS: recvRTS(pktRx_); break; case MAC_Subtype_CTS: recvCTS(pktRx_); break; case MAC_Subtype_ACK: recvACK(pktRx_); break; default: …………………………… } break; case MAC_Type_Data: switch(subtype) { case MAC_Subtype_Data: recvDATA(pktRx_); break; default: fprintf(stderr, "recv_timer2:Invalid MAC Data Subtype %x\n", subtype); exit(1); } break; default: fprintf(stderr, "recv_timer3:Invalid MAC Type %x\n", subtype); exit(1); } done: pktRx_ = 0; rx_resume(); } recv_timer() receiver NAV
recvCTS() Void Mac802_11::recvCTS(Packet *p) { if(tx_state_ != MAC_RTS) { discard(p, DROP_MAC_INVALID_STATE); return; } assert(pktRTS_); Packet::free(pktRTS_); pktRTS_ = 0; assert(pktTx_); mhSend_.stop(); /* * The successful reception of this CTS packet implies * that our RTS was successful. * According to the IEEE spec 9.2.5.3, you must * reset the ssrc_, but not the congestion window. */ ssrc_ = 0; tx_resume(); mac_log(p); }
void Mac802_11::tx_resume() { double rTime; assert(mhSend_.busy() == 0); assert(mhDefer_.busy() == 0); if(pktCTRL_) { mhDefer_.start(phymib_. getSIFS()); } else if(pktRTS_) { if (mhBackoff_.busy() == 0) { rTime = (Random::random() % cw_) * phymib_.getSlotTime(); mhDefer_.start( phymib_.getDIFS() + rTime); } } else if(pktTx_) { if (mhBackoff_.busy() == 0) { hdr_cmn *ch = HDR_CMN(pktTx_); struct hdr_mac802_11 *mh = HDR_MAC802_11(pktTx_); if ((u_int32_t) ch->size() < macmib_.getRTSThreshold() || (u_int32_t) ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) { rTime = (Random::random() % cw_) * phymib_.getSlotTime(); mhDefer_.start(phymib_.getDIFS() + rTime); } else { mhDefer_.start(phymib_.getSIFS()); } } } else if(callback_) { Handler *h = callback_; callback_ = 0; h->handle((Event*) 0); } setTxState(MAC_IDLE); } tx_resume() recv_timer recvRTS recvDATA
rx_resume() void Mac802_11::rx_resume() { … setRxState(MAC_IDLE); } main receiver
check_pktTx() int Mac802_11::check_pktTx() { struct hdr_mac802_11 *mh; double timeout; assert(mhBackoff_.busy() == 0); if(pktTx_ == 0) return -1; mh = HDR_MAC802_11(pktTx_); switch(mh->dh_fc.fc_subtype) { case MAC_Subtype_Data: if(! is_idle()) { sendRTS(ETHER_ADDR(mh->dh_ra)); inc_cw(); mhBackoff_.start(cw_, is_idle()); return 0; } setTxState(MAC_SEND); if((u_int32_t)ETHER_ADDR(mh->dh_ra) != MAC_BROADCAST) timeout = txtime(pktTx_) + DSSS_MaxPropagationDelay + phymib_.getSIFS() + txtime(phymib_.getACKlen(), basicRate_) + DSSS_MaxPropagationDelay; else timeout = txtime(pktTx_); break; default: fprintf(stderr, "check_pktTx:Invalid MAC Control subtype\n"); exit(1); } transmit(pktTx_, timeout); return 0; }
recvACK() void Mac802_11::recvACK(Packet *p) { struct hdr_cmn *ch = HDR_CMN(p); if(tx_state_ != MAC_SEND) { discard(p, DROP_MAC_INVALID_STATE); return; } assert(pktTx_); mhSend_.stop(); if((u_int32_t) HDR_CMN(pktTx_)->size() <= macmib_.getRTSThreshold()) ssrc_ = 0; else slrc_ = 0; rst_cw(); Packet::free(pktTx_); pktTx_ = 0; assert(mhBackoff_.busy() == 0); mhBackoff_.start(cw_, is_idle()); tx_resume(); mac_log(p); }
txtime(double, double) doubleMac802_11::txtime(double psz, double drt){ double dsz = psz - phymib_.getPLCPhdrLen(); int plcp_hdr = phymib_.getPLCPhdrLen() << 3; int datalen = (int)dsz << 3; double t = (((double)plcp_hdr)/phymib_.getPLCPDataRate()) + (((double)datalen)/drt); return(t); } sendDATA
txtime(Packet*) doubleMac802_11::txtime(Packet *p) { struct hdr_cmn *ch = HDR_CMN(p); double t = ch->txtime(); if (t < 0.0) { drop(p, "XXX"); exit(1); } return t; } transmit
How is the RTS/CTS implemented? • Receiving a packet destined for itself recv() -> receive timer started -> recv_timer() -> recvRTS() -> sendCTS() -> tx_resume() -> start defer timer -> rx_resume() -> deferHandler() -> check_pktCTRL() -> transmit() -> recv() -> receive timer started -> recv_timer() -> recvDATA() -> sendACK() -> tx_resume() -> start defer timer -> uptarget_->recv() -> rx_resume() -> deferHandler() -> check_pktCTRL() -> transmit() -> start send timer -> send_timer() -> tx_resume() <- nothing happens, we're done!
recvRTS() void Mac802_11::recvRTS(Packet *p) { struct rts_frame *rf = (struct rts_frame*)p->access(hdr_mac::offset_); if(tx_state_ != MAC_IDLE) { discard(p, DROP_MAC_BUSY); return; } if(pktCTRL_) { discard(p, DROP_MAC_BUSY); return; } sendCTS(ETHER_ADDR(rf->rf_ta), rf->rf_duration); if(mhDefer_.busy()) mhDefer_.stop(); tx_resume(); mac_log(p); }
void Mac802_11::sendCTS(int dst, double rts_duration) { Packet *p = Packet::alloc(); hdr_cmn* ch = HDR_CMN(p); struct cts_frame *cf = (struct cts_frame*)p ->access(hdr_mac::offset_); assert(pktCTRL_ == 0); ch->uid() = 0; ch->ptype() = PT_MAC; ch->size() = phymib_.getCTSlen(); ch->iface() = -2; ch->error() = 0; bzero(cf, MAC_HDR_LEN); cf->cf_fc.fc_protocol_version = MAC_ProtocolVersion; cf->cf_fc.fc_type = MAC_Type_Control; cf->cf_fc.fc_subtype = MAC_Subtype_CTS; cf->cf_fc.fc_to_ds = 0; cf->cf_fc.fc_from_ds = 0; cf->cf_fc.fc_more_frag = 0; cf->cf_fc.fc_retry = 0; cf->cf_fc.fc_pwr_mgt = 0; cf->cf_fc.fc_more_data = 0; cf->cf_fc.fc_wep = 0; cf->cf_fc.fc_order = 0; /* store cts tx time */ ch->txtime() = txtime(ch->size(), basicRate_); /* calculate cts duration */ cf->cf_duration = usec(sec(rts_duration) - phymib_.getSIFS() - txtime(phymib_.getCTSlen(), basicRate_)); pktCTRL_ = p; } sendCTS() CTSheader
int Mac802_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_MAC802_11(pktCTRL_); switch(mh->dh_fc.fc_subtype) { case MAC_Subtype_CTS: if(!is_idle()) { discard(pktCTRL_, DROP_MAC_BUSY); pktCTRL_ = 0; return 0; } setTxState(MAC_CTS); timeout = txtime(phymib_.getCTSlen(), basicRate_) + DSSS_MaxPropagationDelay + sec(mh->dh_duration) + DSSS_MaxPropagationDelay - phymib_.getSIFS() - txtime(phymib_.getACKlen(), basicRate_); break; case MAC_Subtype_ACK: setTxState(MAC_ACK); timeout = txtime(phymib_.getACKlen(), basicRate_); break; default: fprintf(stderr, "check_pktCTRL:Invalid MAC Control subtype\n"); exit(1); } transmit(pktCTRL_, timeout); return 0; } check_pktCTRL
void Mac802_11::recvDATA(Packet *p) { struct hdr_mac802_11 *dh = HDR_MAC802_11(p); u_int32_t dst, src, size; struct hdr_cmn *ch = HDR_CMN(p); dst = ETHER_ADDR(dh->dh_ra); src = ETHER_ADDR(dh->dh_ta); size = ch->size(); ch->size() -= phymib_.getHdrLen11(); ch->num_forwards() += 1; if(dst != MAC_BROADCAST) { if(size >= macmib_.getRTSThreshold()) { if (tx_state_ == MAC_CTS) { assert(pktCTRL_); Packet::free(pktCTRL_); pktCTRL_ = 0; mhSend_.stop(); } else { discard(p, DROP_MAC_BUSY); return; } sendACK(src); tx_resume(); } else { if(pktCTRL_) { discard(p, DROP_MAC_BUSY); return; } sendACK(src); if(mhSend_.busy() == 0) tx_resume(); } } …………………………………………………………………………………………. uptarget_->recv(p, (Handler*) 0); } recvDATA() recv_timer
void Mac802_11::sendACK(int dst) { Packet *p = Packet::alloc(); hdr_cmn* ch = HDR_CMN(p); struct ack_frame *af = (struct ack_frame*)p->access(hdr_mac::offset_); assert(pktCTRL_ == 0); ch->uid() = 0; ch->ptype() = PT_MAC; ch->size() = phymib_.getACKlen(); ch->iface() = -2; ch->error() = 0; bzero(af, MAC_HDR_LEN); af->af_fc.fc_protocol_version = MAC_ProtocolVersion; af->af_fc.fc_type = MAC_Type_Control; af->af_fc.fc_subtype = MAC_Subtype_ACK; af->af_fc.fc_to_ds = 0; af->af_fc.fc_from_ds = 0; af->af_fc.fc_more_frag = 0; af->af_fc.fc_retry = 0; af->af_fc.fc_pwr_mgt = 0; af->af_fc.fc_more_data = 0; af->af_fc.fc_wep = 0; af->af_fc.fc_order = 0; STORE4BYTE(&dst, (af->af_ra)); /* store ack tx time */ ch->txtime() = txtime(ch->size(), basicRate_); /* calculate ack duration */ af->af_duration = 0; pktCTRL_ = p; } sendACK()
DCF with four-way handshaking (cont.) • Errors • Sender sends a RTS but never receives the CTS • Sender sends the data but never receives the ACK • Number of retransmissions • shortRetryLimit : for short frame (frame_length < RTSThreshold) • longRetryLimit : for long frame (frame_length >= RTSThreshold)
When the first RTS fails • Transmitting a packet (RTS loss) recv() -> send() -> sendDATA() and sendRTS() -> start defer timer -> deferHandler() -> check_pktRTS() -> transmit() -> start send timer -> send_timer() -> RetransmitRTS() -> tx_resume() -> backoff timer started -> backoffHandler() -> check_pktRTS() -> transmit The rest is the same as above
When mhSend_ timer expires void Mac802_11::send_timer() { switch(tx_state_) { case MAC_RTS: RetransmitRTS(); break; case MAC_CTS: assert(pktCTRL_); Packet::free(pktCTRL_); pktCTRL_ = 0; break; case MAC_SEND: RetransmitDATA(); break; case MAC_ACK: assert(pktCTRL_); Packet::free(pktCTRL_); pktCTRL_ = 0; break; case MAC_IDLE: break; default: assert(0); } tx_resume(); }
RetransmitRTS() Mac802_11::RetransmitRTS(){ … ssrc_ += 1; if(ssrc_ >= macmib_.getShortRetryLimit()) { discard(pktRTS_, DROP_MAC_RETRY_COUNT_EXCEEDED); pktRTS_ = 0; … discard(pktTx_,DROP_MAC_RETRY_COUNT_EXCEEDED); pktTx_ = 0; ssrc_ = 0; rst_cw(); } else { struct rts_frame *rf; rf = (struct rts_frame*)pktRTS_->access(hdr_mac::offset_); rf->rf_fc.fc_retry = 1; inc_cw(); mhBackoff_.start(cw_, is_idle()); } }
backoffHandler() Void Mac802_11::backoffHandler(){ if(pktCTRL_) { assert(mhSend_.busy() || mhDefer_.busy()); return; } if(check_pktRTS() == 0) return; if(check_pktTx() == 0) return; }
When data lost • Sending a packet (data lost) recv() -> send() -> sendDATA() and sendRTS() -> start defer timer -> deferHandler() -> check_pktRTS() -> transmit() -> recv() -> receive timer started -> recv_timer() -> recvCTS() -> tx_resume() -> start defer timer -> rx_resume() -> deferHandler() -> check_pktTx() -> transmit() -> start send timer -> send_timer() -> RetransmitDATA() -> tx_resume() -> backoff timer started -> backoffHandler() -> check_pktTx() -> transmit The rest is the same as previous
Today’s Outline • How is the RTS/CTS implemented? • Is the default setting for RTS/CTS on or off in ns-2? • How is the NAV implemented? • How is the back-off timer implemented?
DCF • DCF has two access mechanisms for packet transmission : two-way handshaking and four-way handshaking • Using two-way or four-way depends on the RTSThreshold value • If the size of transmitted packet is larger than this value, then four-way is applied
DCF Four-way Two-way sender receiver sender receiver DIFS DIFS RTS data SIFS SIFS CTS ACK SIFS data SIFS ACK
Is the default setting for RTS/CTS on or off in ns-2? • This condition will be checked in sendRTS() (in mac-802_11.cc)
Is the default setting for RTS/CTS on or off in ns-2? (cont.) voidMac802_11::sendRTS(int dst){ … /* If the size of the packet is larger than the RTSThreshold, then perform the RTS/CTS exchange. Also skip if destination is a broadcast */ if( (u_int32_t) HDR_CMN(pktTx_)->size() < macmib_.getRTSThreshold() || (u_int32_t) dst == MAC_BROADCAST) { Packet::free(p); //p = 0; return; }
Is the default setting for RTS/CTS on or off in ns-2? (cont.) • So all we concerned is the value of RTSThreshold • The default value of RTSThreshold is 0 in ns-default.tcl file • Mac/802_11 set RTSThreshold_ 0 • So the “if statement” of previous page is always false, it means that the default setting for RTS/CTS is on in ns-2
Today’s Outline • Is the default setting for RTS/CTS on or off in ns-2? • How is the RTS/CTS implemented? • How is the NAV implemented? • How is the back-off timer implemented?
How is the NAV implemented? • NAV (network allocation vector) indicates the period which the channel is busy. • Each node will update this value when receives RTS or CTS. • This value is according to the duration field of the frames.
How is the NAV implemented? • If a node is not the sender or destination, once it receives the RTS or CTS, it will update its NAV. • This is done in recv_timer() (see next page)
How is the NAV implemented? sendRTS sendCTS
How is the NAV implemented? • Nodes also update the NAV if they detect any error or collision. • In these cases, nodes will defer for EIFS (extension interframe space)
How is the NAV implemented? void Mac802_11::recv_timer() { … /* Handle collisions */ if(rx_state_ == MAC_COLL) { discard(pktRx_, DROP_MAC_COLLISION); set_nav(usec(phymib_.getEIFS())); goto done; } recv_timer
How is the NAV implemented? /* Check to see if this packet was received with errors that the current level of FEC still could not fix all of the problems */ if( ch->error() ) { Packet::free(pktRx_); set_nav(usec(phymib_.getEIFS())); goto done; }
How is the NAV implemented? /* IEEE 802.11 specs, update the NAV */ if(dst != (u_int32_t)index_) { set_nav(mh->dh_duration); }