📄 mac_80211.h
字号:
m_tx_failed=false; m_seq_no=0; SentPackets=RecvPackets=0;}template <class PLD>void MAC80211<PLD>::Stop(){ //printf("%s: sent %d, recv %d\n",GetName(),SentPackets,RecvPackets);}template <class PLD>void MAC80211<PLD>::from_network ( payload_t const& pld, const ether_addr_t& dst_addr, unsigned int size ){ // a new payload packet to be transmitted arrived from the higher layer if(m_state!=MAC_IDLE) { Printf((DumpPackets,"mac%d state: %d, m_last_send: %f, simtime: %f\n",(int)MyEtherAddr, m_state,m_last_send,SimTime())); packet_t::free_pld(pld); // only when mac is in MAC_IDLE can it transmit a payload packet. The // below is to tell the higher layer that transmission has // failed. In all cases an ack must be sent, whether it is a // success or a failure to_network_ack(false); return; } if(size < RTSThreshold || dst_addr == ether_addr_t::BROADCAST ) { m_long_pld=false; m_ssrc=0; } else { m_long_pld=true; m_slrc=0; } m_pldinfo.pld=pld; m_pldinfo.dst_addr=dst_addr; m_pldinfo.size=size; m_seq_no++; // start the defer timer without backoff. This is because // if the medium is still free after difs or eifs then // the packet can be sent immediately without backoff StartDefer(false);}template <class PLD>void MAC80211<PLD>::DeferTimer(trigger_t&){ // deferral timer expires. It is now time to send out the packet assert(m_state==MAC_DEFER); Printf((DumpPackets,"mac%d deferal timer fires \n", (int)MyEtherAddr)); packet_t * np = packet_t::alloc(); // creates a new packet if(m_long_pld==false) { // simply send out the packet without an RTS np->hdr.dh_fc.fc_protocol_version = MAC_ProtocolVersion; np->hdr.dh_fc.fc_type = MAC_Type_Data; np->hdr.dh_fc.fc_subtype = MAC_Subtype_Data; np->hdr.dh_da = m_pldinfo.dst_addr; np->hdr.dh_sa = MyEtherAddr; np->hdr.dh_scontrol = m_seq_no; np->hdr.size = m_pldinfo.size + HDR_LEN; np->hdr.tx_time = np->hdr.size / DataRate; np->pld = m_pldinfo.pld; if( np->hdr.dh_da != ether_addr_t::BROADCAST) { // this function increases the reference count of the packet by 1, // virtually meaning this mac component partly owns the packet (together // with any other components that will receive this packet, because of // the use of reference counting. This mac component will regain the packet // when the ack_timer expires (an ACKTimeout event). np->inc_ref(); np->hdr.dh_duration = usec (m_sifs+ACK_LEN/BasicRate + np->hdr.size/DataRate); // this function sets the ack time. Notice the first argument which is used // to the packet that will be sent out. When the timer expires, whatever stored // here will be returned ack_timer.Set(np, np->hdr.dh_duration*1e-6 + m_difs + SimTime() ); m_state = MAC_ACK; // waiting for ack } else { // it is a broadcast packet. just send it out and no need for ack np->hdr.tx_time = np->hdr.size /BasicRate; np->hdr.dh_duration = 0; // send an ack to network layer, after a delay equal to the transmission time assert(!network_ack_timer.Active()); network_ack_timer.Set(true,SimTime()+np->hdr.tx_time); m_state = MAC_IDLE; } } else { // np is now an RTS packet. Again, this mac component partly owns the packet np->inc_ref(); np->hdr.dh_fc.fc_protocol_version = MAC_ProtocolVersion; np->hdr.dh_fc.fc_type = MAC_Type_Control; np->hdr.dh_fc.fc_subtype = MAC_Subtype_RTS; np->hdr.dh_da = m_pldinfo.dst_addr; np->hdr.dh_sa = MyEtherAddr; np->hdr.size = RTS_LEN; np->hdr.tx_time = np->hdr.size/BasicRate; np->hdr.dh_duration = usec ( 3*m_sifs + CTS_LEN/BasicRate + (m_pldinfo.size + HDR_LEN)/DataRate + ACK_LEN/BasicRate ); // set the cts timer and change state to MAC_CTS cts_timer.Set(np,np->hdr.dh_duration*1e-6 + m_sifs + SimTime()); m_state = MAC_CTS; } // send out the packet immediately. The second argument is the transmission time TxPacket(np,np->hdr.tx_time);}template <class PLD>void MAC80211<PLD>::from_phy ( packet_t* pkt, bool errflag, double power ){ // A packet has arrived from the physical layer. At this time, the first // bit of the packet is just starting transmission // printf("[%f] mac%d receiving %s (%e %d)\n",SimTime(),(int)MyEtherAddr,pkt->dump().c_str(),power,errflag); Printf((DumpPackets,"mac%d start receiving %s (%e,%d)\n",(int)MyEtherAddr,pkt->dump().c_str(),power,errflag)); // if the recv timer is active then another receive is in progress if( recv_timer.Active() ) { packet_t* rx_packet = m_rxinfo.packet; if( power > m_rxinfo.power * CPThreshold) { DropPacket(m_rxinfo.packet,"power too weak"); m_rxinfo.packet=pkt; m_rxinfo.error=errflag; m_rxinfo.power=power; recv_timer.Set(SimTime()+pkt->hdr.tx_time); } else if (m_rxinfo.power > power * CPThreshold) { DropPacket(pkt, "power too weak"); } else { 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_rxinfo.packet=pkt; m_rxinfo.error=errflag; m_rxinfo.power=power; } else { DropPacket(pkt,"receive-receive collision"); } m_rxinfo.error=1; // set the error flag to 1 } } else { m_rxinfo.packet=pkt; m_rxinfo.error=errflag; m_rxinfo.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 double pt=SimTime()-m_defer_start; if(pt>m_ifs) { // pt-m_ifs is the time we have already spent // in the backoff period. Need to adjust // m_backoff_time accordingly m_backoff_time-= pt-m_ifs; assert(m_backoff_time>=0); } defer_timer.Cancel(); Printf((DumpPackets,"mac%d deferral suspended\n",(int)MyEtherAddr)); } }}template <class PLD>void MAC80211<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_rxinfo.packet; Printf((DumpPackets,"mac%d received %s (%e,%d)\n",(int)MyEtherAddr,p->dump().c_str(),m_rxinfo.power,m_rxinfo.error)); // printf("[%f] mac%d received %s (%e,%d)\n",SimTime(),(int)MyEtherAddr,p->dump().c_str(),m_rxinfo.power,m_rxinfo.error); if(m_rxinfo.error==1) // if there is any error { DropPacket(p, "frame error"); m_tx_failed = true; ResumeDefer(); return ; } simtime_t now = SimTime(); // m_last_send is the time last packet had been sent if( now - p->hdr.tx_time < m_last_send ) { // receive-send collision DropPacket(p,"frame error"); m_tx_failed = true; ResumeDefer(); return; } ether_addr_t dst = p->hdr.dh_da; uint8_t type = p->hdr.dh_fc.fc_type; uint8_t subtype = p->hdr.dh_fc.fc_subtype; // set the nav value simtime_t nav = p->hdr.dh_duration*1e-6 + SimTime(); if(nav>m_nav) m_nav=nav; RecvPackets++; //printf(" %d %d\n",(int)p->hdr.dh_sa, (int)MyEtherAddr); if( dst != MyEtherAddr && dst != ether_addr_t::BROADCAST) { if( !Promiscuity || type!= MAC_Type_Data) { DropPacket(p,"wrong destination"); m_tx_failed=false; ResumeDefer(); return; } } m_tx_failed=false; // a transmission has been successful switch(type) { case MAC_Type_Management: DropPacket(p, "unknown MAC packet"); break; case MAC_Type_Control: switch(subtype) { case MAC_Subtype_RTS: RecvRTS(p); ResumeDefer(); break; case MAC_Subtype_CTS: RecvCTS(p); ResumeDefer(); break; case MAC_Subtype_ACK: ResumeDefer(); RecvACK(p); break; default: fprintf(stderr, "recv_timer(1):Invalid MAC Control Subtype %x\n", subtype); break; } break; case MAC_Type_Data: switch(subtype) { case MAC_Subtype_Data: RecvData(p); break; default: fprintf(stderr, "recv_timer(2):Invalid MAC Data Subtype %x\n", subtype); break; } break; default: fprintf(stderr, "recv_timer(3):Invalid MAC Type %x\n", subtype); break; }}template <class PLD>void MAC80211<PLD>::RecvRTS(packet_t* p){ if( m_state != MAC_IDLE && m_state != MAC_DEFER ) { // sorry, I am waiting for a CTS or an ACK. Clearly something // is wrong. A is sending me an RTS while I am communicating // with B. I just ignore A's request since the communication // with B will perhaps be successful in spite of A's presence DropPacket(p,"mac is busy"); return; } // if nav_timer is active then another session (which may or may // not involve this address) is already in the middle, so we have // to ignore this packet if( !nav_timer.Active() ) { // prepare a CTS packet packet_t* np = packet_t::alloc(); np->hdr.dh_fc.fc_protocol_version = MAC_ProtocolVersion; np->hdr.dh_fc.fc_type = MAC_Type_Control; np->hdr.dh_fc.fc_subtype = MAC_Subtype_CTS; np->hdr.size=CTS_LEN; np->hdr.dh_da = p->hdr.dh_sa ; np->hdr.dh_sa=MyEtherAddr; np->hdr.tx_time = np->hdr.size/BasicRate; np->hdr.dh_duration = p->hdr.dh_duration - usec(m_sifs + RTS_LEN/BasicRate); // send out the packet at time SimTime()+m_sifs TxPacket(np,m_sifs,np->hdr.tx_time); // record session info
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -