1 / 21

How to send a unicast packet?

How to send a unicast packet?. Procedure. Roughly takes the following path (when no errors or congestion): recv() -> send() -> sendDATA() and sendRTS() -> start defer timer -> deferHandler() -> check_pktRTS() -> transmit() -> recv() -> receive timer started

elsa
Download Presentation

How to send a unicast packet?

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. How to send a unicast packet?

  2. Procedure Roughly takes the following path (when no errors or congestion): 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!

  3. 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 { ……………………………………………………………………………………… } } back to procedure

  4. 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()); } } } back to procedure

  5. 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 (see 9.6) */ ch->txtime() = txtime(ch->size(), basicRate_ ); dh->dh_duration = 0; } pktTx_ = p; } 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_); Back to send ( ) sendDATA( ) Back to procedure

  6. 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( ) Back to send ( ) Back to procedure

  7. deferHandler( ) void Mac802_11::deferHandler() { assert(pktCTRL_ || pktRTS_ || pktTx_); if( check_pktCTRL() == 0) return; assert(mhBackoff_.busy() == 0); if( check_pktRTS() == 0) return; if( check_pktTx() == 0) return; } Back to procedure

  8. Check_pktCTRL() int Mac802_11::check_pktCTRL() { struct hdr_mac802_11 *mh; double timeout; if(pktCTRL_ == 0) return -1; ……………………. } Back to deferHandler() Back to procedure

  9. check_pktRTS() int Mac802_11::check_pktRTS() { struct hdr_mac802_11 *mh; double timeout; assert(mhBackoff_.busy() == 0); 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; } Back to deferHandler() Back to procedure

  10. 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; } Back to deferHandler() Back to procedure

  11. 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; } Back to recv_timer() Back to procedure

  12. 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() Back to procedure

  13. } 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); } 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); } tx_resume() Back to recvCTS Back to recvACK Back to procedure

  14. rx_resume( ) Void Mac802_11::rx_resume() { assert(pktRx_ == 0); assert(mhRecv_.busy() == 0); setRxState(MAC_IDLE); } Back to recv_timer Back to procedure

  15. 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); } Back to recv_timer() Back to procedure

  16. 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); } Back to recv_timer() Back to procedure

  17. inline void Mac802_11::transmit(Packet *p, double timeout) { tx_active_ = 1; if (EOTtarget_) { assert (eotPacket_ == NULL); eotPacket_ = p->copy(); } /* * If I'm transmitting without doing CS, such as when sending an ACK, any incoming packet will be * "missed“ and hence, must be discarded. */ if(rx_state_ != MAC_IDLE) { struct hdr_mac802_11 *dh = HDR_MAC802_11(p); assert(dh->dh_fc.fc_type == MAC_Type_Control); assert(dh->dh_fc.fc_subtype == MAC_Subtype_ACK); assert(pktRx_); struct hdr_cmn *ch = HDR_CMN(pktRx_); ch->error() = 1; /* force packet discard */ } /* * 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. */ downtarget_->recv(p->copy(), this); mhSend_.start(timeout); mhIF_.start(txtime(p)); } Back to check_pktRTS() Back to procedure

  18. txtime( ) /* * txtime() - calculate tx time for packet of size "psz" bytes * at rate "drt" bps */ double Mac802_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); } Back to sendDATA() Back to procedure

  19. 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(); } Back to transmit() Back to procedure

  20. When mhIF_ timer expires void Mac802_11::txHandler() { if (EOTtarget_) { assert(eotPacket_); EOTtarget_->recv(eotPacket_, (Handler *) 0); eotPacket_ = NULL; } tx_active_ = 0; } Back to transmit() Back to procedure

  21. References • mac-802_11.cc, mac-802_11.h • mac-timers.cc, mac-timers.h • http://www.ece.rice.edu/~jpr/ns/docs/802_11.html#DeferTimer

More Related