📄 mac_80211.h
字号:
/************************************************************************** Copyright 2003 Gilbert (Gang) Chen, Boleslaw K. Szymanski and* Rensselaer Polytechnic Institute. All worldwide rights reserved.* A license to use, copy, modify and distribute this software for* non-commercial research purposes only is hereby granted, provided* that this copyright notice and accompanying disclaimer is not* modified or removed from the software.** DISCLAIMER: The software is distributed "AS IS" without any* express or implied warranty, including but not limited to, any* implied warranties of merchantability or fitness for a particular* purpose or any warranty of non-infringement of any current or* pending patent rights. The authors of the software make no* representations about the suitability of this software for any* particular purpose. The entire risk as to the quality and* performance of the software is with the user. Should the software* prove defective, the user assumes the cost of all necessary* servicing, repair or correction. In particular, neither Rensselaer* Polytechnic Institute, nor the authors of the software are liable* for any indirect, special, consequential, or incidental damages* related to the software, to the maximum extent the law permits.*************************************************************************/#ifndef mac80211_h#define mac80211_h#include <map>template <class PLD>struct MAC80211_Struct{ // for frame format enum { MAC_ProtocolVersion=0x00, MAC_Type_Management=0x00, MAC_Type_Control=0x01, MAC_Type_Data=0x02, MAC_Type_Reserved=0x03, MAC_Subtype_RTS=0x0b, MAC_Subtype_CTS=0x0c, MAC_Subtype_ACK=0x0d, MAC_Subtype_Data=0x00 }; // Frame control fields struct frame_control { u_char fc_subtype : 4; u_char fc_type : 2; u_char fc_protocol_version : 2; u_char fc_order : 1; u_char fc_wep : 1; u_char fc_more_data : 1; u_char fc_pwr_mgt : 1; u_char fc_retry : 1; u_char fc_more_frag : 1; u_char fc_from_ds : 1; u_char fc_to_ds : 1; }; struct hdr_struct { // fields defined in 802.11 standard frame_control dh_fc; uint16_t dh_duration; ether_addr_t dh_da; ether_addr_t dh_sa; ether_addr_t dh_bssid; uint16_t dh_scontrol; // extra fields to keep track of certain information. // They should not be counted when calculating the length of the packet double tx_time; // packet transmission time double wave_length; // needed to calculate path loss unsigned int size; bool dump(std::string& str) const { std::string type; bool payload=false; switch(dh_fc.fc_type) { case MAC_Type_Control: switch(dh_fc.fc_subtype) { case MAC_Subtype_RTS: type="RTS"; break; case MAC_Subtype_CTS: type="CST"; break; case MAC_Subtype_ACK: type="ACK"; break; default: type="UNKNOWN"; } break; case MAC_Type_Data: if(dh_fc.fc_subtype == 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; } }; typedef smart_packet_t<hdr_struct,PLD> packet_t; typedef PLD payload_t; // physical layer parameters static int CWMin; static int CWMax; static double SlotTime; static double SIFSTime; // mac layer parameters static unsigned int RTSThreshold; static unsigned int ShortRetryLimit; static unsigned int LongRetryLimit; // lengths of various frames or headers static int PLCP_HDR_LEN; static int HDR_LEN; static int RTS_LEN; static int CTS_LEN; static int ACK_LEN; static int FCS_LEN; // (Gang) my understanding is that unicast data frames are sent at // DataRate, while all other frames are sent at BasicRate static double DataRate; static double BasicRate; static double CPThreshold; };// define values for simulation related parameterstemplate <class PLD> int MAC80211_Struct<PLD>::CWMin=31;template <class PLD> int MAC80211_Struct<PLD>::CWMax=1023;template <class PLD> double MAC80211_Struct<PLD>::SlotTime=0.000020;template <class PLD> double MAC80211_Struct<PLD>::SIFSTime=0.000010;template <class PLD> unsigned int MAC80211_Struct<PLD>::RTSThreshold=3000;template <class PLD> unsigned int MAC80211_Struct<PLD>::ShortRetryLimit=3;template <class PLD> unsigned int MAC80211_Struct<PLD>::LongRetryLimit=4;template <class PLD> int MAC80211_Struct<PLD>::PLCP_HDR_LEN = (144 + 48) >> 3;template <class PLD> int MAC80211_Struct<PLD>::HDR_LEN = PLCP_HDR_LEN + FCS_LEN + 4*ether_addr_t::LENGTH + 6;template <class PLD> int MAC80211_Struct<PLD>::RTS_LEN = PLCP_HDR_LEN + FCS_LEN + 2*ether_addr_t::LENGTH + 6;template <class PLD> int MAC80211_Struct<PLD>::CTS_LEN = PLCP_HDR_LEN + FCS_LEN + 1*ether_addr_t::LENGTH + 6;template <class PLD> int MAC80211_Struct<PLD>::ACK_LEN = PLCP_HDR_LEN + FCS_LEN + 1*ether_addr_t::LENGTH + 6;template <class PLD> int MAC80211_Struct<PLD>::FCS_LEN = 4;template <class PLD> double MAC80211_Struct<PLD>::DataRate=1.0e6/8;template <class PLD> double MAC80211_Struct<PLD>::BasicRate=1.0e6/8;template <class PLD> double MAC80211_Struct<PLD>::CPThreshold=10; /* * MAC80211 requires a template parameter PLD, which specifies * the type of payload that will be transmitted by the mac layer. In * particular, PLD could be a plain of data packet, or a pointer * to a data packet. The underlying packet management handles both * cases elegantly. */template <class PLD>component MAC80211 : public TypeII, public MAC80211_Struct<PLD>{ public: int SentPackets,RecvPackets; enum MAC_STATE { MAC_IDLE = 0x0000, // nothing to do MAC_DEFER = 0x0001, // has a packet to send MAC_CTS = 0x0002, // waiting for CTS MAC_ACK = 0x0004, // waiting for ACK }; ether_addr_t MyEtherAddr; bool DumpPackets; bool Promiscuity; inport void from_network ( payload_t const & pld, const ether_addr_t& dst, unsigned int size ); outport void to_network_data ( payload_t& pld, const ether_addr_t & dst); outport void to_network_ack ( bool errflag ); inport void from_phy ( packet_t* pkt, bool errflag, double power ); outport void to_phy (packet_t* pkt); Timer <trigger_t> defer_timer; // for backoff Timer <trigger_t> recv_timer; // for receiving a packet Timer <MAC80211_Struct<PLD>::packet_t*> cts_timer; // for CTSTimeout Timer <MAC80211_Struct<PLD>::packet_t*> ack_timer; // for ACKTimeout Timer <trigger_t> nav_timer; // for NAV Timer <bool> network_ack_timer; inport void NetworkAckTimer(bool&); Timer <MAC80211_Struct<PLD>::packet_t*> phy_timer; inport void PhyTimer(packet_t*&); void Start(); // called when simulation starts void Stop(); // called when simulation stops MAC80211(); virtual ~MAC80211(); // functions to be bound to inports and timers. Just from the name // you can tell which inport or timer it is bound to. inport void DeferTimer(trigger_t&); inport void RecvTimer(trigger_t&); inport void CTSTimer(packet_t*&); inport void ACKTimer(packet_t*&); inport void NAVTimer(trigger_t&); private: // functions to be called by others void RecvRTS(packet_t* p); void RecvCTS(packet_t* p); void RecvData(packet_t* p); void RecvACK(packet_t* p); // We have two TxPacket functions: one starts transmission // immediately, the other will wait for a specified delay inline void TxPacket(packet_t* p, simtime_t tx_time); inline void TxPacket(packet_t* p, simtime_t start_time, simtime_t tx_time); // In StartDefer(), the mac state changes from MAC_IDLE to // MAC_DEFER; a new backoff time must be sampled. In // ResumeDefer(), the mac state should already be MAC_DEFER // (otherwise the function just exits); the old value of backoff // time will be used. void StartDefer(bool backoff); inline void ResumeDefer(); // drop a packet and tells why void DropPacket(packet_t* p, const char*); // convert from sec to usec; copied from ns2 uint16_t usec(simtime_t t) { return (uint16_t)floor((t *= 1e6) + 0.5); } MAC_STATE m_state; // MAC's current state double m_nav; // Network Allocation Vector int m_cw; // Contention Window double m_backoff_time; // Backoff Time unsigned int m_ssrc; // STA Short Retry Count unsigned int m_slrc; // STA Long Retry Count double m_sifs; // Short Interframe Space double m_difs; // DCF Interframe Space double m_eifs; // Extended Interframe Space double m_ifs; // equal to either m_difs or m_eifs double m_defer_start; // when deferral started bool m_in_session; // if involved in an RTS/CTS session ether_addr_t m_session_peer; // who initiated the session struct { payload_t pld; ether_addr_t dst_addr; unsigned int size; } m_pldinfo; struct { packet_t * packet; bool error; double power; } m_rxinfo; bool m_tx_failed; // if last transmission succeeded bool m_long_pld; // if the length of current pld >= RTSThreshold simtime_t m_last_send; // the end tx time of last packet uint16_t m_seq_no; // sequence number // a STL container containing pairs of address and sequence // number. It is used to remove duplicate data packet. The // container is sorted so the address has to be comparable typedef std::map<ether_addr_t, uint16_t, ether_addr_t::compare> cache_t; cache_t m_recv_cache;};template <class PLD>MAC80211<PLD>::MAC80211(){ connect defer_timer.to_component, DeferTimer; connect recv_timer.to_component, RecvTimer; connect cts_timer.to_component, CTSTimer; connect ack_timer.to_component, ACKTimer; connect nav_timer.to_component, NAVTimer; connect network_ack_timer.to_component, NetworkAckTimer; connect phy_timer.to_component, PhyTimer;}template <class PLD>MAC80211<PLD>::~MAC80211(){ }template <class PLD>void MAC80211<PLD>::Start(){ // perform some initialization tasks m_state=MAC_IDLE; m_nav=0.0; m_cw=CWMin; m_last_send=0.0; m_ssrc=0; m_slrc=0; m_sifs=SIFSTime; m_difs=m_sifs+SlotTime; m_eifs=m_sifs+ACK_LEN/DataRate+m_difs;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -