160 likes | 229 Views
Learn how to send multicast packets over 802.11 network in NS-2 simulation platform by tracing mac-802_11.cc and mac-802_11.h files under mac folder. Study the procedure for receiving, sending, sending DATA, sending RTS, starting defer timer, defer handler, checking packet transmission, and more. Understand the code snippets and functions involved in transmitting and handling packets.
E N D
How to send a multicast packet over 802.11 network? Trace mac-802_11.cc and mac-802_11.h under mac folder of ns-2.28
Procedure recv() -> send() -> sendDATA() and sendRTS() -> start defer timer -> deferHandler() -> check_pktTx() -> transmit() -> done!
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; } ………………………………….. } Back to procedure
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
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
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
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
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
check_pktRTS() int Mac802_11::check_pktRTS() { struct hdr_mac802_11 *mh; double timeout; assert(mhBackoff_.busy() == 0); if(pktRTS_ == 0) return -1; ………………………………………. } Back to deferHandler() Back to procedure
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
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
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 procedure
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
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
RetransmitDATA() void Mac802_11::RetransmitDATA() { struct hdr_cmn *ch; struct hdr_mac802_11 *mh; u_int32_t *rcount, thresh; assert(mhBackoff_.busy() == 0); assert(pktTx_); assert(pktRTS_ == 0); ch = HDR_CMN(pktTx_); mh = HDR_MAC802_11(pktTx_); if((u_int32_t)ETHER_ADDR(mh->dh_ra) == MAC_BROADCAST) { Packet::free(pktTx_); pktTx_ = 0; rst_cw(); mhBackoff_.start(cw_, is_idle()); return; } …………………………………………………………… } Back to transmit() Back to procedure
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