diff --git a/src/devices/wifi/wifi-mac-header.cc b/src/devices/wifi/wifi-mac-header.cc new file mode 100644 index 000000000..e736283a6 --- /dev/null +++ b/src/devices/wifi/wifi-mac-header.cc @@ -0,0 +1,969 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#include +#include "ns3/address-utils.h" +#include "wifi-mac-header.h" + +#define MAC80211HEADER_DEBUG 1 + +#ifdef MAC80211HEADER_DEBUG +#include +# define TRACE(x) \ +std::Cout << "MAC80211HEADER " << x << std::Endl; +#else +# define TRACE(x) +#endif + + +namespace ns3 { + +enum { + TYPE_MGT = 0, + TYPE_CTL = 1, + TYPE_DATA = 2 +}; + +enum { + SUBTYPE_CTL_BACKREQ = 8, + SUBTYPE_CTL_BACKRESP = 9, + SUBTYPE_CTL_RTS = 11, + SUBTYPE_CTL_CTS = 12, + SUBTYPE_CTL_ACK = 13 +}; + +WifiMacHeader::WifiMacHeader () +{} +WifiMacHeader::~WifiMacHeader () +{} + +void +WifiMacHeader::SetDsFrom (void) +{ + m_ctrlFromDs = 1; +} +void +WifiMacHeader::SetDsNotFrom (void) +{ + m_ctrlFromDs = 0; +} +void +WifiMacHeader::SetDsTo (void) +{ + m_ctrlToDs = 1; +} +void +WifiMacHeader::SetDsNotTo (void) +{ + m_ctrlToDs = 0; +} + +void +WifiMacHeader::SetAddr1 (Mac48Address address) +{ + m_addr1 = address; +} +void +WifiMacHeader::SetAddr2 (Mac48Address address) +{ + m_addr2 = address; +} +void +WifiMacHeader::SetAddr3 (Mac48Address address) +{ + m_addr3 = address; +} +void +WifiMacHeader::SetAddr4 (Mac48Address address) +{ + m_addr4 = address; +} +void +WifiMacHeader::SetAssocReq (void) +{ + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 0; +} +void +WifiMacHeader::SetAssocResp (void) +{ + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 1; +} +void +WifiMacHeader::SetProbeReq (void) +{ + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 4; +} +void +WifiMacHeader::SetProbeResp (void) +{ + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 5; +} +void +WifiMacHeader::SetTypeData (void) +{ + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 0; +} +void +WifiMacHeader::SetType (enum WifiMacType_e type) +{ + switch (type) { + case WIFI_MAC_CTL_BACKREQ: + m_ctrlType = TYPE_CTL; + m_ctrlSubtype = SUBTYPE_CTL_BACKREQ; + break; + case WIFI_MAC_CTL_BACKRESP: + m_ctrlType = TYPE_CTL; + m_ctrlSubtype = SUBTYPE_CTL_BACKRESP; + break; + case WIFI_MAC_CTL_RTS: + m_ctrlType = TYPE_CTL; + m_ctrlSubtype = SUBTYPE_CTL_RTS; + break; + case WIFI_MAC_CTL_CTS: + m_ctrlType = TYPE_CTL; + m_ctrlSubtype = SUBTYPE_CTL_CTS; + break; + case WIFI_MAC_CTL_ACK: + m_ctrlType = TYPE_CTL; + m_ctrlSubtype = SUBTYPE_CTL_ACK; + break; + case WIFI_MAC_MGT_ASSOCIATION_REQUEST: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 0; + break; + case WIFI_MAC_MGT_ASSOCIATION_RESPONSE: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 1; + break; + case WIFI_MAC_MGT_REASSOCIATION_REQUEST: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 2; + break; + case WIFI_MAC_MGT_REASSOCIATION_RESPONSE: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 3; + break; + case WIFI_MAC_MGT_PROBE_REQUEST: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 4; + break; + case WIFI_MAC_MGT_PROBE_RESPONSE: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 5; + break; + case WIFI_MAC_MGT_BEACON: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 8; + break; + case WIFI_MAC_MGT_DISASSOCIATION: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 10; + break; + case WIFI_MAC_MGT_AUTHENTICATION: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 11; + break; + case WIFI_MAC_MGT_DEAUTHENTICATION: + m_ctrlType = TYPE_MGT; + m_ctrlSubtype = 12; + break; + + case WIFI_MAC_DATA: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 0; + break; + case WIFI_MAC_DATA_CFACK: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 1; + break; + case WIFI_MAC_DATA_CFPOLL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 2; + break; + case WIFI_MAC_DATA_CFACK_CFPOLL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 3; + break; + case WIFI_MAC_DATA_NULL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 4; + break; + case WIFI_MAC_DATA_NULL_CFACK: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 5; + break; + case WIFI_MAC_DATA_NULL_CFPOLL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 6; + break; + case WIFI_MAC_DATA_NULL_CFACK_CFPOLL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 7; + break; + case WIFI_MAC_QOSDATA: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 8; + break; + case WIFI_MAC_QOSDATA_CFACK: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 9; + break; + case WIFI_MAC_QOSDATA_CFPOLL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 10; + break; + case WIFI_MAC_QOSDATA_CFACK_CFPOLL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 11; + break; + case WIFI_MAC_QOSDATA_NULL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 12; + break; + case WIFI_MAC_QOSDATA_NULL_CFPOLL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 14; + break; + case WIFI_MAC_QOSDATA_NULL_CFACK_CFPOLL: + m_ctrlType = TYPE_DATA; + m_ctrlSubtype = 15; + break; + } + m_ctrlToDs = 0; + m_ctrlFromDs = 0; +} +void +WifiMacHeader::SetDuration (uint16_t duration) +{ + m_duration = duration; +} +void +WifiMacHeader::SetDurationUs (uint64_t duration_us) +{ + assert (duration_us <= (1<<16) - 1); + m_duration = static_cast (duration_us); +} + +void WifiMacHeader::SetId (uint16_t id) +{ + m_duration = id; +} +void WifiMacHeader::SetSequenceNumber (uint16_t seq) +{ + m_seqSeq = seq; +} +void WifiMacHeader::SetFragmentNumber (uint8_t frag) +{ + m_seqFrag = frag; +} +void WifiMacHeader::SetNoMoreFragments (void) +{ + m_ctrlMoreFrag = 0; +} +void WifiMacHeader::SetMoreFragments (void) +{ + m_ctrlMoreFrag = 1; +} +void WifiMacHeader::SetRetry (void) +{ + m_ctrlRetry = 1; +} +void WifiMacHeader::SetNoRetry (void) +{ + m_ctrlRetry = 0; +} +void WifiMacHeader::SetQosTid (uint8_t tid) +{ + m_qosTid = tid; +} +void WifiMacHeader::SetQosTxopLimit (uint8_t txop) +{ + m_qosStuff = txop; +} + +Mac48Address +WifiMacHeader::GetAddr1 (void) const +{ + return m_addr1; +} +Mac48Address +WifiMacHeader::GetAddr2 (void) const +{ + return m_addr2; +} +Mac48Address +WifiMacHeader::GetAddr3 (void) const +{ + return m_addr3; +} +Mac48Address +WifiMacHeader::GetAddr4 (void) const +{ + return m_addr4; +} +enum WifiMacType_e +WifiMacHeader::GetType (void) const +{ + switch (m_ctrlType) { + case TYPE_MGT: + switch (m_ctrlSubtype) { + case 0: + return WIFI_MAC_MGT_ASSOCIATION_REQUEST; + break; + case 1: + return WIFI_MAC_MGT_ASSOCIATION_RESPONSE; + break; + case 2: + return WIFI_MAC_MGT_REASSOCIATION_REQUEST; + break; + case 3: + return WIFI_MAC_MGT_REASSOCIATION_RESPONSE; + break; + case 4: + return WIFI_MAC_MGT_PROBE_REQUEST; + break; + case 5: + return WIFI_MAC_MGT_PROBE_RESPONSE; + break; + case 8: + return WIFI_MAC_MGT_BEACON; + break; + case 10: + return WIFI_MAC_MGT_DISASSOCIATION; + break; + case 11: + return WIFI_MAC_MGT_AUTHENTICATION; + break; + case 12: + return WIFI_MAC_MGT_DEAUTHENTICATION; + break; + + } + break; + case TYPE_CTL: + switch (m_ctrlSubtype) { + case SUBTYPE_CTL_BACKREQ: + return WIFI_MAC_CTL_BACKREQ; + break; + case SUBTYPE_CTL_BACKRESP: + return WIFI_MAC_CTL_BACKRESP; + break; + case SUBTYPE_CTL_RTS: + return WIFI_MAC_CTL_RTS; + break; + case SUBTYPE_CTL_CTS: + return WIFI_MAC_CTL_CTS; + break; + case SUBTYPE_CTL_ACK: + return WIFI_MAC_CTL_ACK; + break; + } + break; + case TYPE_DATA: + switch (m_ctrlSubtype) { + case 0: + return WIFI_MAC_DATA; + break; + case 1: + return WIFI_MAC_DATA_CFACK; + break; + case 2: + return WIFI_MAC_DATA_CFPOLL; + break; + case 3: + return WIFI_MAC_DATA_CFACK_CFPOLL; + break; + case 4: + return WIFI_MAC_DATA_NULL; + break; + case 5: + return WIFI_MAC_DATA_NULL_CFACK; + break; + case 6: + return WIFI_MAC_DATA_NULL_CFPOLL; + break; + case 7: + return WIFI_MAC_DATA_NULL_CFACK_CFPOLL; + break; + case 8: + return WIFI_MAC_QOSDATA; + break; + case 9: + return WIFI_MAC_QOSDATA_CFACK; + break; + case 10: + return WIFI_MAC_QOSDATA_CFPOLL; + break; + case 11: + return WIFI_MAC_QOSDATA_CFACK_CFPOLL; + break; + case 12: + return WIFI_MAC_QOSDATA_NULL; + break; + case 14: + return WIFI_MAC_QOSDATA_NULL_CFPOLL; + break; + case 15: + return WIFI_MAC_QOSDATA_NULL_CFACK_CFPOLL; + break; + + } + break; + } + // NOTREACHED + assert (false); + return (enum WifiMacType_e)-1; +} +bool +WifiMacHeader::IsFromDs (void) const +{ + return m_ctrlFromDs == 1; +} +bool +WifiMacHeader::IsToDs (void) const +{ + return m_ctrlToDs == 1; +} + +bool +WifiMacHeader::IsData (void) const +{ + return (m_ctrlType == TYPE_DATA)?true:false; + +} +bool +WifiMacHeader::IsQosData (void) const +{ + return (m_ctrlType == TYPE_DATA && (m_ctrlSubtype & 0x08))?true:false; +} +bool +WifiMacHeader::IsCtl (void) const +{ + return (m_ctrlType == TYPE_CTL)?true:false; +} +bool +WifiMacHeader::IsMgt (void) const +{ + return (m_ctrlType == TYPE_MGT)?true:false; +} +bool +WifiMacHeader::IsCfpoll (void) const +{ + switch (GetType ()) { + case WIFI_MAC_DATA_CFPOLL: + case WIFI_MAC_DATA_CFACK_CFPOLL: + case WIFI_MAC_DATA_NULL_CFPOLL: + case WIFI_MAC_DATA_NULL_CFACK_CFPOLL: + case WIFI_MAC_QOSDATA_CFPOLL: + case WIFI_MAC_QOSDATA_CFACK_CFPOLL: + case WIFI_MAC_QOSDATA_NULL_CFPOLL: + case WIFI_MAC_QOSDATA_NULL_CFACK_CFPOLL: + return true; + break; + default: + return false; + break; + } +} +bool +WifiMacHeader::IsRts (void) const +{ + return (GetType () == WIFI_MAC_CTL_RTS)?true:false; +} +bool +WifiMacHeader::IsCts (void) const +{ + return (GetType () == WIFI_MAC_CTL_CTS)?true:false; +} +bool +WifiMacHeader::IsAck (void) const +{ + return (GetType () == WIFI_MAC_CTL_ACK)?true:false; +} +bool +WifiMacHeader::IsAssocReq (void) const +{ + return (GetType () == WIFI_MAC_MGT_ASSOCIATION_REQUEST)?true:false; +} +bool +WifiMacHeader::IsAssocResp (void) const +{ + return (GetType () == WIFI_MAC_MGT_ASSOCIATION_RESPONSE)?true:false; +} +bool +WifiMacHeader::IsReassocReq (void) const +{ + return (GetType () == WIFI_MAC_MGT_REASSOCIATION_REQUEST)?true:false; +} +bool +WifiMacHeader::IsReassocResp (void) const +{ + return (GetType () == WIFI_MAC_MGT_REASSOCIATION_RESPONSE)?true:false; +} +bool +WifiMacHeader::IsProbeReq (void) const +{ + return (GetType () == WIFI_MAC_MGT_PROBE_REQUEST)?true:false; +} +bool +WifiMacHeader::IsProbeResp (void) const +{ + return (GetType () == WIFI_MAC_MGT_PROBE_RESPONSE)?true:false; +} +bool +WifiMacHeader::IsBeacon (void) const +{ + return (GetType () == WIFI_MAC_MGT_BEACON)?true:false; +} +bool +WifiMacHeader::IsDisassociation (void) const +{ + return (GetType () == WIFI_MAC_MGT_DISASSOCIATION)?true:false; +} +bool +WifiMacHeader::IsAuthentication (void) const +{ + return (GetType () == WIFI_MAC_MGT_AUTHENTICATION)?true:false; +} +bool +WifiMacHeader::IsDeauthentication (void) const +{ + return (GetType () == WIFI_MAC_MGT_DEAUTHENTICATION)?true:false; +} + + +uint16_t +WifiMacHeader::GetDuration (void) const +{ + return m_duration; +} +uint64_t +WifiMacHeader::GetDurationUs (void) const +{ + return m_duration; +} +uint16_t +WifiMacHeader::GetSequenceControl (void) const +{ + return (m_seqSeq << 4) | m_seqFrag; +} +uint16_t +WifiMacHeader::GetSequenceNumber (void) const +{ + return m_seqSeq; +} +uint16_t +WifiMacHeader::GetFragmentNumber (void) const +{ + return m_seqFrag; +} +bool +WifiMacHeader::IsRetry (void) const +{ + return (m_ctrlRetry == 1)?true:false; +} +bool +WifiMacHeader::IsMoreFragments (void) const +{ + return (m_ctrlMoreFrag == 1)?true:false; +} +bool +WifiMacHeader::IsQosBlockAck (void) const +{ + assert (IsQosData ()); + return (m_qosAckPolicy == 3)?true:false; +} +bool +WifiMacHeader::IsQosNoAck (void) const +{ + assert (IsQosData ()); + return (m_qosAckPolicy == 1)?true:false; +} +bool +WifiMacHeader::IsQosAck (void) const +{ + assert (IsQosData ()); + return (m_qosAckPolicy == 0)?true:false; +} +uint8_t +WifiMacHeader::GetQosTid (void) const +{ + assert (IsQosData ()); + return m_qosTid; +} +uint8_t +WifiMacHeader::GetQosTxopLimit (void) const +{ + assert (IsQosData ()); + return m_qosStuff; +} + +uint16_t +WifiMacHeader::GetFrameControl (void) const +{ + uint16_t val = 0; + val |= (m_ctrlType << 2) & (0x3<<2); + val |= (m_ctrlSubtype << 4) & (0xf<<4); + val |= (m_ctrlToDs << 8) & (0x1<<8); + val |= (m_ctrlFromDs << 9) & (0x1<<9); + val |= (m_ctrlMoreFrag << 10) & (0x1<<10); + val |= (m_ctrlRetry << 11) & (0x1<<11); + val |= (m_ctrlMoreData << 13) & (0x1<<13); + val |= (m_ctrlWep << 14) & (0x1<<14); + val |= (m_ctrlOrder << 15) & (0x1<<15); + return val; +} + +uint16_t +WifiMacHeader::GetQosControl (void) const +{ + uint16_t val = 0; + val |= m_qosTid; + val |= m_qosEosp << 4; + val |= m_qosAckPolicy << 5; + val |= m_qosStuff << 8; + return val; +} + +void +WifiMacHeader::SetFrameControl (uint16_t ctrl) +{ + m_ctrlType = (ctrl >> 2) & 0x03; + m_ctrlSubtype = (ctrl >> 4) & 0x0f; + m_ctrlToDs = (ctrl >> 8) & 0x01; + m_ctrlFromDs = (ctrl >> 9) & 0x01; + m_ctrlMoreFrag = (ctrl >> 10) & 0x01; + m_ctrlRetry = (ctrl >> 11) & 0x01; + m_ctrlMoreData = (ctrl >> 13) & 0x01; + m_ctrlWep = (ctrl >> 14) & 0x01; + m_ctrlOrder = (ctrl >> 15) & 0x01; +} +void +WifiMacHeader::SetSequenceControl (uint16_t seq) +{ + m_seqFrag = seq & 0x0f; + m_seqSeq = (seq >> 4) & 0x0fff; +} +void +WifiMacHeader::SetQosControl (uint16_t qos) +{ + m_qosTid = qos & 0x000f; + m_qosEosp = (qos >> 4) & 0x0001; + m_qosAckPolicy = (qos >> 5) & 0x0003; + m_qosStuff = (qos >> 8) & 0x00ff; +} + + +void +WifiMacHeader::SetDurationS (double duration) +{ + uint16_t us = (uint16_t)(duration * 1000000); + us &= 0x7fff; + SetDuration (us); +} + +uint32_t +WifiMacHeader::GetSize (void) const +{ + uint32_t size = 0; + switch (m_ctrlType) { + case TYPE_MGT: + size = 2+2+6+6+6+2; + break; + case TYPE_CTL: + switch (m_ctrlSubtype) { + case SUBTYPE_CTL_RTS: + size = 2+2+6+6; + break; + case SUBTYPE_CTL_CTS: + case SUBTYPE_CTL_ACK: + size = 2+2+6; + break; + case SUBTYPE_CTL_BACKREQ: + case SUBTYPE_CTL_BACKRESP: + // NOT IMPLEMENTED + assert (false); + break; + } + break; + case TYPE_DATA: + size = 2+2+6+6+6+2; + if (m_ctrlToDs && m_ctrlFromDs) { + size += 6; + } + if (m_ctrlSubtype & 0x08) { + size += 2; + } + break; + } + return size; +} +char const * +WifiMacHeader::GetTypeString (void) const +{ +#define FOO(x) \ +case WIFI_MAC_ ## x: \ + return #x; \ + break; + + switch (GetType ()) { + FOO (CTL_RTS); + FOO (CTL_CTS); + FOO (CTL_ACK); + FOO (CTL_BACKREQ); + FOO (CTL_BACKRESP); + + FOO (MGT_BEACON); + FOO (MGT_ASSOCIATION_REQUEST); + FOO (MGT_ASSOCIATION_RESPONSE); + FOO (MGT_DISASSOCIATION); + FOO (MGT_REASSOCIATION_REQUEST); + FOO (MGT_REASSOCIATION_RESPONSE); + FOO (MGT_PROBE_REQUEST); + FOO (MGT_PROBE_RESPONSE); + FOO (MGT_AUTHENTICATION); + FOO (MGT_DEAUTHENTICATION); + + FOO (DATA); + FOO (DATA_CFACK); + FOO (DATA_CFPOLL); + FOO (DATA_CFACK_CFPOLL); + FOO (DATA_NULL); + FOO (DATA_NULL_CFACK); + FOO (DATA_NULL_CFPOLL); + FOO (DATA_NULL_CFACK_CFPOLL); + FOO (QOSDATA); + FOO (QOSDATA_CFACK); + FOO (QOSDATA_CFPOLL); + FOO (QOSDATA_CFACK_CFPOLL); + FOO (QOSDATA_NULL); + FOO (QOSDATA_NULL_CFPOLL); + FOO (QOSDATA_NULL_CFACK_CFPOLL); + default: + return "ERROR"; + } +#undef FOO +} + +uint32_t +WifiMacHeader::GetUid (void) +{ + static uint32_t uid = AllocateUid ("WifiMacHeader.ns3.inria.fr"); + return uid; +} + +std::string +WifiMacHeader::GetName (void) const +{ + return "802.11"; +} + +void +WifiMacHeader::PrintFrameControl (std::ostream &os) const +{ + os << "(" + << "ToDS=" << m_ctrlToDs << ", FromDS=" << m_ctrlFromDs + << ", MoreFrag=" << m_ctrlMoreFrag << ", Retry=" << m_ctrlRetry + << ", MoreData=" << m_ctrlMoreData + << ")"; +} + +void +WifiMacHeader::Print (std::ostream &os) const +{ + os << GetTypeString () << " "; + switch (GetType ()) + { + case WIFI_MAC_CTL_RTS: + os << "Duration/ID=" << m_duration << "us" + << ", RA=" << m_addr1 << ", TA=" << m_addr2; + break; + case WIFI_MAC_CTL_CTS: + case WIFI_MAC_CTL_ACK: + os << "Duration/ID=" << m_duration << "us" + << ", RA=" << m_addr1; + break; + case WIFI_MAC_CTL_BACKREQ: + break; + case WIFI_MAC_CTL_BACKRESP: + break; + + case WIFI_MAC_MGT_BEACON: + case WIFI_MAC_MGT_ASSOCIATION_REQUEST: + case WIFI_MAC_MGT_ASSOCIATION_RESPONSE: + case WIFI_MAC_MGT_DISASSOCIATION: + case WIFI_MAC_MGT_REASSOCIATION_REQUEST: + case WIFI_MAC_MGT_REASSOCIATION_RESPONSE: + case WIFI_MAC_MGT_PROBE_REQUEST: + case WIFI_MAC_MGT_PROBE_RESPONSE: + case WIFI_MAC_MGT_AUTHENTICATION: + case WIFI_MAC_MGT_DEAUTHENTICATION: + PrintFrameControl (os); + os << " Duration/ID=" << m_duration << "us" + << ", DA=" << m_addr1 << ", SA=" << m_addr2 + << ", BSSID=" << m_addr3 << ", FragNumber=" << m_seqFrag + << ", SeqNumber=" << m_seqSeq; + break; + case WIFI_MAC_DATA: + PrintFrameControl (os); + os << " Duration/ID=" << m_duration << "us"; + if (!m_ctrlToDs && !m_ctrlFromDs) + { + os << "DA=" << m_addr1 << ", SA=" << m_addr2 << ", BSSID=" << m_addr3; + } + else if (!m_ctrlToDs && m_ctrlFromDs) + { + os << "DA=" << m_addr1 << ", SA=" << m_addr3 << ", BSSID=" << m_addr2; + } + else if (m_ctrlToDs && !m_ctrlFromDs) + { + os << "DA=" << m_addr3 << ", SA=" << m_addr2 << ", BSSID=" << m_addr1; + } + else if (m_ctrlToDs && m_ctrlFromDs) + { + os << "DA=" << m_addr3 << ", SA=" << m_addr4 << ", RA=" << m_addr1 << ", TA=" << m_addr2; + } + else + { + NS_ASSERT (false); + } + os << ", FragNumber=" << m_seqFrag + << ", SeqNumber=" << m_seqSeq; + break; + case WIFI_MAC_DATA_CFACK: + case WIFI_MAC_DATA_CFPOLL: + case WIFI_MAC_DATA_CFACK_CFPOLL: + case WIFI_MAC_DATA_NULL: + case WIFI_MAC_DATA_NULL_CFACK: + case WIFI_MAC_DATA_NULL_CFPOLL: + case WIFI_MAC_DATA_NULL_CFACK_CFPOLL: + case WIFI_MAC_QOSDATA: + case WIFI_MAC_QOSDATA_CFACK: + case WIFI_MAC_QOSDATA_CFPOLL: + case WIFI_MAC_QOSDATA_CFACK_CFPOLL: + case WIFI_MAC_QOSDATA_NULL: + case WIFI_MAC_QOSDATA_NULL_CFPOLL: + case WIFI_MAC_QOSDATA_NULL_CFACK_CFPOLL: + break; + } +} +uint32_t +WifiMacHeader::GetSerializedSize (void) const +{ + return GetSize (); +} +void +WifiMacHeader::Serialize (Buffer::Iterator i) const +{ + i.WriteHtonU16 (GetFrameControl ()); + i.WriteHtonU16 (m_duration); + WriteTo (i, m_addr1); + switch (m_ctrlType) { + case TYPE_MGT: + WriteTo (i, m_addr2); + WriteTo (i, m_addr3); + i.WriteHtonU16 (GetSequenceControl ()); + break; + case TYPE_CTL: + switch (m_ctrlSubtype) { + case SUBTYPE_CTL_RTS: + WriteTo (i, m_addr2); + break; + case SUBTYPE_CTL_CTS: + case SUBTYPE_CTL_ACK: + break; + case SUBTYPE_CTL_BACKREQ: + case SUBTYPE_CTL_BACKRESP: + // NOT IMPLEMENTED + assert (false); + break; + default: + //NOTREACHED + assert (false); + break; + } + break; + case TYPE_DATA: { + WriteTo (i, m_addr2); + WriteTo (i, m_addr3); + i.WriteHtonU16 (GetSequenceControl ()); + if (m_ctrlToDs && m_ctrlFromDs) { + WriteTo (i, m_addr4); + } + if (m_ctrlSubtype & 0x08) { + i.WriteHtonU16 (GetQosControl ()); + } + } break; + default: + //NOTREACHED + assert (false); + break; + } +} +uint32_t +WifiMacHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + uint16_t frame_control = i.ReadNtohU16 (); + SetFrameControl (frame_control); + m_duration = i.ReadNtohU16 (); + ReadFrom (i, m_addr1); + switch (m_ctrlType) { + case TYPE_MGT: + ReadFrom (i, m_addr2); + ReadFrom (i, m_addr3); + SetSequenceControl (i.ReadNtohU16 ()); + break; + case TYPE_CTL: + switch (m_ctrlSubtype) { + case SUBTYPE_CTL_RTS: + ReadFrom (i, m_addr2); + break; + case SUBTYPE_CTL_CTS: + case SUBTYPE_CTL_ACK: + break; + case SUBTYPE_CTL_BACKREQ: + case SUBTYPE_CTL_BACKRESP: + // NOT IMPLEMENTED + assert (false); + break; + } + break; + case TYPE_DATA: + ReadFrom (i, m_addr2); + ReadFrom (i, m_addr3); + SetSequenceControl (i.ReadNtohU16 ()); + if (m_ctrlToDs && m_ctrlFromDs) { + ReadFrom (i, m_addr4); + } + if (m_ctrlSubtype & 0x08) { + SetQosControl (i.ReadNtohU16 ()); + } + break; + } + return i.GetDistanceFrom (start); +} + +}; // namespace ns3 diff --git a/src/devices/wifi/wifi-mac-header.h b/src/devices/wifi/wifi-mac-header.h new file mode 100644 index 000000000..18973fecc --- /dev/null +++ b/src/devices/wifi/wifi-mac-header.h @@ -0,0 +1,182 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#ifndef WIFI_MAC_HEADER_H +#define WIFI_MAC_HEADER_H + +#include "ns3/header.h" +#include "ns3/mac48-address.h" +#include + +namespace ns3 { + +enum WifiMacType_e { + WIFI_MAC_CTL_RTS = 0, + WIFI_MAC_CTL_CTS, + WIFI_MAC_CTL_ACK, + WIFI_MAC_CTL_BACKREQ, + WIFI_MAC_CTL_BACKRESP, + + WIFI_MAC_MGT_BEACON, + WIFI_MAC_MGT_ASSOCIATION_REQUEST, + WIFI_MAC_MGT_ASSOCIATION_RESPONSE, + WIFI_MAC_MGT_DISASSOCIATION, + WIFI_MAC_MGT_REASSOCIATION_REQUEST, + WIFI_MAC_MGT_REASSOCIATION_RESPONSE, + WIFI_MAC_MGT_PROBE_REQUEST, + WIFI_MAC_MGT_PROBE_RESPONSE, + WIFI_MAC_MGT_AUTHENTICATION, + WIFI_MAC_MGT_DEAUTHENTICATION, + + WIFI_MAC_DATA, + WIFI_MAC_DATA_CFACK, + WIFI_MAC_DATA_CFPOLL, + WIFI_MAC_DATA_CFACK_CFPOLL, + WIFI_MAC_DATA_NULL, + WIFI_MAC_DATA_NULL_CFACK, + WIFI_MAC_DATA_NULL_CFPOLL, + WIFI_MAC_DATA_NULL_CFACK_CFPOLL, + WIFI_MAC_QOSDATA, + WIFI_MAC_QOSDATA_CFACK, + WIFI_MAC_QOSDATA_CFPOLL, + WIFI_MAC_QOSDATA_CFACK_CFPOLL, + WIFI_MAC_QOSDATA_NULL, + WIFI_MAC_QOSDATA_NULL_CFPOLL, + WIFI_MAC_QOSDATA_NULL_CFACK_CFPOLL, +}; + +class WifiMacHeader : public Header +{ +public: + WifiMacHeader (); + ~WifiMacHeader (); + static uint32_t GetUid (void); + std::string GetName (void) const; + void Print (std::ostream &os) const; + uint32_t GetSerializedSize (void) const; + void Serialize (Buffer::Iterator start) const; + uint32_t Deserialize (Buffer::Iterator start); + + + void SetAssocReq (void); + void SetAssocResp (void); + void SetProbeReq (void); + void SetProbeResp (void); + void SetTypeData (void); + void SetDsFrom (void); + void SetDsNotFrom (void); + void SetDsTo (void); + void SetDsNotTo (void); + void SetAddr1 (Mac48Address address); + void SetAddr2 (Mac48Address address); + void SetAddr3 (Mac48Address address); + void SetAddr4 (Mac48Address address); + void SetType (enum WifiMacType_e type); + void SetDuration (uint16_t duration); + void SetDurationUs (uint64_t duration); + void SetId (uint16_t id); + void SetSequenceNumber (uint16_t seq); + void SetFragmentNumber (uint8_t frag); + void SetNoMoreFragments (void); + void SetMoreFragments (void); + void SetRetry (void); + void SetNoRetry (void); + void SetQosTid (uint8_t tid); + void SetQosTxopLimit (uint8_t txop); + + Mac48Address GetAddr1 (void) const; + Mac48Address GetAddr2 (void) const; + Mac48Address GetAddr3 (void) const; + Mac48Address GetAddr4 (void) const; + enum WifiMacType_e GetType (void) const; + bool IsFromDs (void) const; + bool IsToDs (void) const; + bool IsData (void) const; + bool IsQosData (void) const; + bool IsCtl (void) const; + bool IsMgt (void) const; + bool IsCfpoll (void) const; + bool IsRts (void) const; + bool IsCts (void) const; + bool IsAck (void) const; + bool IsAssocReq (void) const; + bool IsAssocResp (void) const; + bool IsReassocReq (void) const; + bool IsReassocResp (void) const; + bool IsProbeReq (void) const; + bool IsProbeResp (void) const; + bool IsBeacon (void) const; + bool IsDisassociation (void) const; + bool IsAuthentication (void) const; + bool IsDeauthentication (void) const; + uint16_t GetDuration (void) const; + uint64_t GetDurationUs (void) const; + uint16_t GetSequenceControl (void) const; + uint16_t GetSequenceNumber (void) const; + uint16_t GetFragmentNumber (void) const; + bool IsRetry (void) const; + bool IsMoreFragments (void) const; + bool IsQosBlockAck (void) const; + bool IsQosNoAck (void) const; + bool IsQosAck (void) const; + uint8_t GetQosTid (void) const; + uint8_t GetQosTxopLimit (void) const; + + void SetDurationS (double duration); + uint32_t GetSize (void) const; + char const *GetTypeString (void) const; + + +private: + uint16_t GetFrameControl (void) const; + uint16_t GetQosControl (void) const; + void SetFrameControl (uint16_t control); + void SetSequenceControl (uint16_t seq); + void SetQosControl (uint16_t qos); + void PrintFrameControl (std::ostream &os) const; + + uint16_t m_ctrlType : 2; + uint16_t m_ctrlSubtype : 4; + uint16_t m_ctrlToDs : 1; + uint16_t m_ctrlFromDs : 1; + uint16_t m_ctrlMoreFrag : 1; + uint16_t m_ctrlRetry : 1; + uint16_t m_ctrlPwrMgt : 1; + uint16_t m_ctrlMoreData : 1; + uint16_t m_ctrlWep : 1; + uint16_t m_ctrlOrder : 1; + uint16_t m_duration; + Mac48Address m_addr1; + Mac48Address m_addr2; + Mac48Address m_addr3; + uint16_t m_seqFrag : 4; + uint16_t m_seqSeq : 12; + Mac48Address m_addr4; + uint16_t m_qosTid : 4; + uint16_t m_qosEosp : 1; + uint16_t m_qosAckPolicy : 2; + uint16_t m_qosStuff: 8; +}; + +}; // namespace ns3 + + + +#endif /* WIFI_MAC_HEADER_H */