📄 bcast_mac.h
字号:
send_timer.Set(m_tx_end); m_state=MAC_SEND; Printf((DumpPackets,"mac%d sends %s until %f\n",(int)MyEtherAddr,np->dump().c_str(),m_tx_end)); to_phy(np); SentPackets++;}template <class PLD>void BcastMAC<PLD>::SendTimer(trigger_t&){ m_state=MAC_IDLE; to_network_ack(!m_sr_collision);}template <class PLD>void BcastMAC<PLD>::AckTimer( bool &flag){ m_state=MAC_IDLE; to_network_ack(flag); return;}template <class PLD>void BcastMAC<PLD>::cancel(){ if(m_state==MAC_DEFER) { defer_timer.Cancel(); m_state=MAC_IDLE; packet_t::free_pld(m_pldinf.pld); assert(ack_timer.Active()==false); ack_timer.Set(true,SimTime()); }}template <class PLD>void BcastMAC<PLD>::from_phy( packet_t *pkt, bool errflag, double power){ RecvPackets++; m_sr_collision=true; // A packet has arrived from the physical layer. At this time, the // first bit of the packet is just starting transmission // if the recv timer is active then another receive is in progress if( recv_timer.Active() ) { packet_t* rx_packet = m_rxinf.packet; // if the power of the new packet is high enough, discard the old packet if( power > m_rxinf.power * CPThreshold) { DropPacket(m_rxinf.packet,"power too weak"); m_rxinf.packet=pkt; m_rxinf.errflag=errflag; m_rxinf.power=power; recv_timer.Set(SimTime()+pkt->hdr.tx_time); } // otherwise, if the old packet was powerful enough, drop the new packet else if (m_rxinf.power > power * CPThreshold) { DropPacket(pkt, "power too weak"); } // otherwise, power levels are too close, so drop both packets else { packet_t *p1 = pkt, *p2 = m_rxinf.packet; simtime_t end_time = SimTime() + pkt->hdr.tx_time; // to decide which lasts longer. The longer one takes the recv timer. if( end_time > recv_timer.GetTime() ) { recv_timer.Set(end_time); DropPacket(rx_packet, "receive-receive collision"); m_rxinf.packet=pkt; m_rxinf.errflag=errflag; m_rxinf.power=power; } else { DropPacket(pkt,"receive-receive collision"); } rrCollisions++; m_rxinf.errflag = true; // set the error flag to true to_network_recv_recv_coll( p1->pld, p2->pld); // pass collision to routing layer// to_network_recv_recv_coll( pkt->pld, m_rxinf.packet->pld); // pass collision to routing layer } } else { m_rxinf.packet=pkt; m_rxinf.errflag=errflag; m_rxinf.power=power; // the recv timer expires as soon as the receive is done recv_timer.Set(pkt->hdr.tx_time + SimTime()); if(m_state==MAC_DEFER) { // if it is in the MAC_DEFER state, defer_timer must be // active. Have to defer it. assert(defer_timer.Active()); // pt is the elapsed time after deferral starts defer_timer.Cancel(); m_pldinf.delay -= SimTime() - m_defer_start; } }}template <class PLD>void BcastMAC<PLD>::RecvTimer( trigger_t &){ // recv timer expires, meaning a packet has just been completely // received. Previously in the FromPhy function if there are // outgoing backoff activity then it had been suspended // (deferred). Therefore on every exit of this function, it must // be checked by calling ResumeDefer() whether there is any // outgoing payload packet to be sent packet_t* p=m_rxinf.packet; Printf((DumpPackets,"mac%d receives %s (%e,%d)\n",(int)MyEtherAddr,p->dump().c_str(),m_rxinf.power,m_rxinf.errflag)); if(m_rxinf.errflag==1) // if there is any error { DropPacket(p, "frame error"); ResumeDefer(); return ; } simtime_t now = SimTime(); // m_tx_end is the time last packet had been sent if( now - p->hdr.tx_time < m_tx_end ) { // receive-send collision DropPacket(p,"receive-send collision"); ResumeDefer(); return; } u_int8_t type = p->hdr.dh_fc.fc_type; u_int8_t subtype = p->hdr.dh_fc.fc_subtype; switch(type) { case MAC_Type_Management: DropPacket(p, "unknown MAC packet"); break; case MAC_Type_Control: DropPacket(p, "not a DATA packet"); break; case MAC_Type_Data: switch(subtype) { case MAC_Subtype_Data: ResumeDefer(); RecvData(p); return; default: fprintf(stderr, "mac%d recv_timer(2):Invalid MAC Data Subtype %x\n",(int)MyEtherAddr, subtype); break; } break; default: fprintf(stderr, "mac%d recv_timer(3):Invalid MAC Type %x\n", (int)MyEtherAddr,subtype); break; } ResumeDefer();}template <class PLD>void BcastMAC<PLD>::RecvData( packet_t *p){ // maintain a database of latest sequence numbers received // from each neighbor cache_t::iterator src=m_recv_cache.find(p->hdr.dh_sa); if(src!=m_recv_cache.end()) { // src->second is the latest sequence number // recently seen from the same source if(src->second==p->hdr.dh_scontrol) { // duplicate data packets. It seems that the source // did not receive the ack in the last round of // transmissions DropPacket(p,"duplicated DATA packet"); return; } else { // update the sequence number src->second=p->hdr.dh_scontrol; } } else { // source not found in the neighbor list, so add it to the cache m_recv_cache.insert(make_pair(p->hdr.dh_sa,p->hdr.dh_scontrol)); } // increase the reference count of the payload by one. This is to // claim that I now partly own the payload. The ownership will be // transferred to the hight layer. p->inc_pld_ref(); // forward the payload contained in the data packet to higher layer. to_network_data(p->pld,m_rxinf.power); p->free(); // discard the data packet;}template <class PLD>void BcastMAC<PLD>::StartDefer(){ // if the state is MAC_DEFER then ResumeDefer instead of this function must be called assert(m_state==MAC_IDLE); assert(defer_timer.Active()==false); Printf((DumpPackets, "mac%d deferring\n",(int)MyEtherAddr)); // if the recv timer is active then do nothing except changing // the state to MAC_DEFER, because it is guaranteed that at the // end of RecvTimer, backoff must be resumed. if(!recv_timer.Active()) { m_defer_start = SimTime(); defer_timer.Set( m_defer_start+m_pldinf.delay); } m_state=MAC_DEFER;}template <class PLD>void BcastMAC<PLD>::ResumeDefer(){ if(m_state!=MAC_DEFER)return; assert(defer_timer.Active()==false); m_defer_start=SimTime(); defer_timer.Set(m_defer_start+m_pldinf.delay+IFS); Printf((DumpPackets, "mac%d resumes deferring: %f \n",(int)MyEtherAddr,m_pldinf.delay));}template <class PLD>void BcastMAC<PLD>::DropPacket( packet_t *p, const char *reason){ Printf((DumpPackets,"mac%d drops %s (%s)\n",(int)MyEtherAddr,p->dump().c_str(),reason)); p->free();}template <class PLD>bool BcastMAC_Struct<PLD>::hdr_struct::dump( std::string &str) const{ std::string type; bool payload=false; switch(dh_fc.fc_type) { case BcastMAC_Struct<PLD>::MAC_Type_Control: switch(dh_fc.fc_subtype) { case BcastMAC_Struct<PLD>::MAC_Subtype_RTS: type="RTS"; break; case BcastMAC_Struct<PLD>::MAC_Subtype_CTS: type="CST"; break; case BcastMAC_Struct<PLD>::MAC_Subtype_ACK: type="ACK"; break; default: type="UNKNOWN"; } break; case BcastMAC_Struct<PLD>::MAC_Type_Data: if(dh_fc.fc_subtype == BcastMAC_Struct<PLD>::MAC_Subtype_Data) { payload=true; if(dh_da!=ether_addr_t::BROADCAST) type="DATA"; else type="BROADCAST"; } else type="UNKNOWN"; break; default: type="UNKNOWN"; break; } char buffer[100]; sprintf(buffer,"%f %s %d -> %d", tx_time, type.c_str(), (int)(dh_sa), (int)(dh_da)); str=buffer; return payload;}#endif /* broadcast_mac_h */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -