diff --git a/src/wifi/model/msdu-aggregator.cc b/src/wifi/model/msdu-aggregator.cc index 88c9a9a2f..48c0486af 100644 --- a/src/wifi/model/msdu-aggregator.cc +++ b/src/wifi/model/msdu-aggregator.cc @@ -75,36 +75,6 @@ MsduAggregator::GetSizeIfAggregated (uint16_t msduSize, uint16_t amsduSize) return amsduSize + CalculatePadding (amsduSize) + 14 + msduSize; } -void -MsduAggregator::Aggregate (Ptr msdu, Ptr amsdu, - Mac48Address src, Mac48Address dest) const -{ - NS_LOG_FUNCTION (this); - NS_ASSERT (amsdu); - - // pad the previous A-MSDU subframe if the A-MSDU is not empty - if (amsdu->GetSize () > 0) - { - uint8_t padding = CalculatePadding (amsdu->GetSize ()); - - if (padding) - { - Ptr pad = Create (padding); - amsdu->AddAtEnd (pad); - } - } - - // add A-MSDU subframe header and MSDU - AmsduSubframeHeader hdr; - hdr.SetDestinationAddr (dest); - hdr.SetSourceAddr (src); - hdr.SetLength (static_cast (msdu->GetSize ())); - - Ptr tmp = msdu->Copy (); - tmp->AddHeader (hdr); - amsdu->AddAtEnd (tmp); -} - Ptr MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid, WifiTxVector txVector, uint32_t ampduSize, @@ -145,10 +115,8 @@ MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid, return 0; } - Ptr amsdu = Create (); + Ptr amsdu = Create (Create (), (*peekedIt)->GetHeader ()); uint8_t nMsdu = 0; - WifiMacHeader header = (*peekedIt)->GetHeader (); - Time tstamp = (*peekedIt)->GetTimeStamp (); // We need to keep track of the first MSDU. When it is processed, it is not known // if aggregation will succeed or not. WifiMacQueue::ConstIterator first = peekedIt; @@ -160,7 +128,7 @@ MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid, { // check if aggregating the peeked MSDU violates the A-MSDU size limit uint16_t newAmsduSize = GetSizeIfAggregated ((*peekedIt)->GetPacket ()->GetSize (), - amsdu->GetSize ()); + amsdu->GetPacket ()->GetSize ()); if (newAmsduSize > maxAmsduSize) { @@ -170,33 +138,25 @@ MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid, // check if the A-MSDU obtained by aggregating the peeked MSDU violates // the A-MPDU size limit or the PPDU duration limit - if (!qosTxop->GetLow ()->IsWithinSizeAndTimeLimits (header.GetSize () + newAmsduSize + WIFI_MAC_FCS_LENGTH, + if (!qosTxop->GetLow ()->IsWithinSizeAndTimeLimits (amsdu->GetHeader ().GetSize () + newAmsduSize + + WIFI_MAC_FCS_LENGTH, recipient, tid, txVector, ampduSize, ppduDurationLimit)) { NS_LOG_DEBUG ("No other MSDU can be aggregated"); break; } - // We can now safely aggregate the MSDU to the A-MSDU - Aggregate ((*peekedIt)->GetPacket (), amsdu, - qosTxop->MapSrcAddressForAggregation (header), - qosTxop->MapDestAddressForAggregation (header)); - - /* "The expiration of the A-MSDU lifetime timer occurs only when the lifetime - * timer of all of the constituent MSDUs of the A-MSDU have expired" (Section - * 10.12 of 802.11-2016) - */ - // The timestamp of the A-MSDU is the most recent among those of the MSDUs - tstamp = Max (tstamp, (*peekedIt)->GetTimeStamp ()); - + // The MSDU can be aggregated to the A-MSDU. // If it is the first MSDU, move to the next one if (nMsdu == 0) { + amsdu = Copy (*peekedIt); peekedIt++; } // otherwise, remove it from the queue else { + amsdu->Aggregate (*peekedIt); peekedIt = queue->Remove (peekedIt); } @@ -214,10 +174,7 @@ MsduAggregator::GetNextAmsdu (Mac48Address recipient, uint8_t tid, // Aggregation succeeded, we have to remove the first MSDU queue->Remove (first); - header.SetQosAmsdu (); - header.SetAddr3 (qosTxop->GetLow ()->GetBssid ()); - - return Create (amsdu, header, tstamp); + return amsdu; } uint8_t diff --git a/src/wifi/model/msdu-aggregator.h b/src/wifi/model/msdu-aggregator.h index 5cd4655f5..e55a8957c 100644 --- a/src/wifi/model/msdu-aggregator.h +++ b/src/wifi/model/msdu-aggregator.h @@ -25,6 +25,7 @@ #include "ns3/nstime.h" #include "wifi-mode.h" #include "qos-utils.h" +#include namespace ns3 { @@ -57,17 +58,6 @@ public: MsduAggregator (); virtual ~MsduAggregator (); - /** - * Aggregate an MSDU to an A-MSDU. - * - * \param msdu the MSDU. - * \param amsdu the A-MSDU. - * \param src the source address. - * \param dest the destination address - */ - void Aggregate (Ptr msdu, Ptr amsdu, - Mac48Address src, Mac48Address dest) const; - /** * Compute the size of the A-MSDU resulting from the aggregation of an MSDU of * size msduSize and an A-MSDU of size amsduSize. @@ -137,7 +127,6 @@ public: */ void SetEdcaQueues (EdcaQueues map); -private: /** * Calculate how much padding must be added to the end of an A-MSDU of the * given size if a new MSDU is added. @@ -149,6 +138,7 @@ private: */ static uint8_t CalculatePadding (uint16_t amsduSize); +private: EdcaQueues m_edca; //!< the map of EDCA queues }; diff --git a/src/wifi/model/wifi-mac-queue-item.cc b/src/wifi/model/wifi-mac-queue-item.cc index da7afb848..d9f430e35 100644 --- a/src/wifi/model/wifi-mac-queue-item.cc +++ b/src/wifi/model/wifi-mac-queue-item.cc @@ -41,6 +41,10 @@ WifiMacQueueItem::WifiMacQueueItem (Ptr p, const WifiMacHeader & h m_header (header), m_tstamp (tstamp) { + if (header.IsQosData () && header.IsQosAmsdu ()) + { + m_msduList = MsduAggregator::Deaggregate (p->Copy ()); + } } WifiMacQueueItem::~WifiMacQueueItem () @@ -83,6 +87,108 @@ WifiMacQueueItem::GetSize (void) const return m_packet->GetSize () + m_header.GetSerializedSize () + WIFI_MAC_FCS_LENGTH; } +void +WifiMacQueueItem::Aggregate (Ptr msdu) +{ + NS_ASSERT (msdu != 0); + NS_LOG_FUNCTION (this << *msdu); + NS_ABORT_MSG_IF (!msdu->GetHeader ().IsQosData () || msdu->GetHeader ().IsQosAmsdu (), + "Only QoS data frames that do not contain an A-MSDU can be aggregated"); + + if (m_msduList.empty ()) + { + // An MSDU is going to be aggregated to this MPDU, hence this has to be an A-MSDU now + Ptr firstMsdu = Create (*this); + m_packet = Create (); + DoAggregate (firstMsdu); + + m_header.SetQosAmsdu (); + // Set Address3 according to Table 9-26 of 802.11-2016 + if (m_header.IsToDs () && !m_header.IsFromDs ()) + { + // from STA to AP: BSSID is in Address1 + m_header.SetAddr3 (m_header.GetAddr1 ()); + } + else if (!m_header.IsToDs () && m_header.IsFromDs ()) + { + // from AP to STA: BSSID is in Address2 + m_header.SetAddr3 (m_header.GetAddr2 ()); + } + // in the WDS case (ToDS = FromDS = 1), both Address 3 and Address 4 need + // to be set to the BSSID, but neither Address 1 nor Address 2 contain the + // BSSID. Hence, it is left up to the caller to set these Address fields. + } + DoAggregate (msdu); +} + +void +WifiMacQueueItem::DoAggregate (Ptr msdu) +{ + NS_LOG_FUNCTION (this << *msdu); + + // build the A-MSDU Subframe header + AmsduSubframeHeader hdr; + /* + * (See Table 9-26 of 802.11-2016) + * + * ToDS | FromDS | DA | SA + * 0 | 0 | Addr1 | Addr2 + * 0 | 1 | Addr1 | Addr3 + * 1 | 0 | Addr3 | Addr2 + * 1 | 1 | Addr3 | Addr4 + */ + hdr.SetDestinationAddr (msdu->GetHeader ().IsToDs () ? msdu->GetHeader ().GetAddr3 () + : msdu->GetHeader ().GetAddr1 ()); + hdr.SetSourceAddr (!msdu->GetHeader ().IsFromDs () ? msdu->GetHeader ().GetAddr2 () + : (!msdu->GetHeader ().IsToDs () + ? msdu->GetHeader ().GetAddr3 () + : msdu->GetHeader ().GetAddr4 ())); + hdr.SetLength (static_cast (msdu->GetPacket ()->GetSize ())); + + m_msduList.push_back ({msdu->GetPacket ()->Copy (), hdr}); + + // build the A-MSDU + NS_ASSERT (m_packet); + Ptr amsdu = m_packet->Copy (); + + // pad the previous A-MSDU subframe if the A-MSDU is not empty + if (m_packet->GetSize () > 0) + { + uint8_t padding = MsduAggregator::CalculatePadding (m_packet->GetSize ()); + + if (padding) + { + amsdu->AddAtEnd (Create (padding)); + } + } + + // add A-MSDU subframe header and MSDU + Ptr amsduSubframe = msdu->GetPacket ()->Copy (); + amsduSubframe->AddHeader (hdr); + amsdu->AddAtEnd (amsduSubframe); + m_packet = amsdu; + + /* "The expiration of the A-MSDU lifetime timer occurs only when the lifetime + * timer of all of the constituent MSDUs of the A-MSDU have expired" (Section + * 10.12 of 802.11-2016) + */ + // The timestamp of the A-MSDU is the most recent among those of the MSDUs + m_tstamp = Max (m_tstamp, msdu->GetTimeStamp ()); +} + + +MsduAggregator::DeaggregatedMsdusCI +WifiMacQueueItem::begin (void) +{ + return m_msduList.begin (); +} + +MsduAggregator::DeaggregatedMsdusCI +WifiMacQueueItem::end (void) +{ + return m_msduList.end (); +} + void WifiMacQueueItem::Print (std::ostream& os) const { diff --git a/src/wifi/model/wifi-mac-queue-item.h b/src/wifi/model/wifi-mac-queue-item.h index f99b7dc41..040102e0d 100644 --- a/src/wifi/model/wifi-mac-queue-item.h +++ b/src/wifi/model/wifi-mac-queue-item.h @@ -26,6 +26,8 @@ #include "ns3/nstime.h" #include "wifi-mac-header.h" +#include "msdu-aggregator.h" +#include "amsdu-subframe-header.h" namespace ns3 { @@ -96,6 +98,27 @@ public: */ uint32_t GetSize (void) const; + /** + * \brief Aggregate the MSDU contained in the given MPDU to this MPDU (thus + * constituting an A-MSDU). Note that the given MPDU cannot contain + * an A-MSDU. + * \param msdu the MPDU containing the MSDU to aggregate + */ + void Aggregate (Ptr msdu); + + /** + * \brief Get a constant iterator pointing to the first MSDU in the list of aggregated MSDUs. + * + * \return a constant iterator pointing to the first MSDU in the list of aggregated MSDUs + */ + MsduAggregator::DeaggregatedMsdusCI begin (void); + /** + * \brief Get a constant iterator indicating past-the-last MSDU in the list of aggregated MSDUs. + * + * \return a constant iterator indicating past-the-last MSDU in the list of aggregated MSDUs + */ + MsduAggregator::DeaggregatedMsdusCI end (void); + /** * \brief Print the item contents. * \param os output stream in which the data should be printed. @@ -103,9 +126,18 @@ public: virtual void Print (std::ostream &os) const; private: - Ptr m_packet; //!< The packet contained in this queue item - WifiMacHeader m_header; //!< Wifi MAC header associated with the packet - Time m_tstamp; //!< timestamp when the packet arrived at the queue + /** + * \brief Aggregate the MSDU contained in the given MPDU to this MPDU (thus + * constituting an A-MSDU). Note that the given MPDU cannot contain + * an A-MSDU. + * \param msdu the MPDU containing the MSDU to aggregate + */ + void DoAggregate (Ptr msdu); + + Ptr m_packet; //!< The packet (MSDU or A-MSDU) contained in this queue item + WifiMacHeader m_header; //!< Wifi MAC header associated with the packet + Time m_tstamp; //!< timestamp when the packet arrived at the queue + MsduAggregator::DeaggregatedMsdus m_msduList; //!< The list of aggregated MSDUs included in this MPDU }; /**