A Discrete-Event Network Simulator
API
wifi-tx-parameters.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #include "wifi-tx-parameters.h"
22 #include "wifi-mac-queue-item.h"
23 #include "wifi-mac-trailer.h"
24 #include "msdu-aggregator.h"
25 #include "mpdu-aggregator.h"
26 #include "wifi-protection.h"
27 #include "wifi-acknowledgment.h"
28 #include "ns3/packet.h"
29 #include "ns3/log.h"
30 
31 namespace ns3 {
32 
33 NS_LOG_COMPONENT_DEFINE ("WifiTxParameters");
34 
35 
36 void
38 {
39  NS_LOG_FUNCTION (this);
40 
41  // Reset the current info
42  m_info.clear ();
44  m_protection.reset (nullptr);
45  m_acknowledgment.reset (nullptr);
47 }
48 
51 {
52  auto infoIt = m_info.find (receiver);
53 
54  if (infoIt == m_info.end ())
55  {
56  return nullptr;
57  }
58  return &infoIt->second;
59 }
60 
63 {
64  return m_info;
65 }
66 
67 void
69 {
70  NS_LOG_FUNCTION (this << *mpdu);
71 
72  const WifiMacHeader& hdr = mpdu->GetHeader ();
73 
74  auto infoIt = m_info.find (hdr.GetAddr1 ());
75 
76  if (infoIt == m_info.end ())
77  {
78  // this is an MPDU starting a new PSDU
79  std::map<uint8_t, std::set<uint16_t>> seqNumbers;
80  if (hdr.IsQosData ())
81  {
82  seqNumbers[hdr.GetQosTid ()] = {hdr.GetSequenceNumber ()};
83  }
84 
85  // Insert the info about the given frame
86  m_info.emplace (hdr.GetAddr1 (),
87  PsduInfo {hdr, static_cast<uint16_t> (mpdu->GetPacketSize ()), 0, seqNumbers});
88  return;
89  }
90 
91  // a PSDU for the receiver of the given MPDU is already being built
92  NS_ASSERT_MSG ((hdr.IsQosData () && !hdr.HasData ()) || infoIt->second.amsduSize > 0,
93  "An MPDU can only be aggregated to an existing (A-)MPDU");
94 
95  // The (A-)MSDU being built is included in an A-MPDU subframe
96  infoIt->second.ampduSize = MpduAggregator::GetSizeIfAggregated (infoIt->second.header.GetSize ()
97  + infoIt->second.amsduSize
99  infoIt->second.ampduSize);
100  infoIt->second.header = hdr;
101  infoIt->second.amsduSize = mpdu->GetPacketSize ();
102 
103  if (hdr.IsQosData ())
104  {
105  auto ret = infoIt->second.seqNumbers.emplace (hdr.GetQosTid (),
106  std::set<uint16_t> {hdr.GetSequenceNumber ()});
107 
108  if (!ret.second)
109  {
110  // insertion did not happen because an entry with the same TID already exists
111  ret.first->second.insert (hdr.GetSequenceNumber ());
112  }
113  }
114 }
115 
116 uint32_t
118 {
119  NS_LOG_FUNCTION (this << *mpdu);
120 
121  auto infoIt = m_info.find (mpdu->GetHeader ().GetAddr1 ());
122 
123  if (infoIt == m_info.end ())
124  {
125  // this is an MPDU starting a new PSDU
127  {
128  // All MPDUs are sent with the A-MPDU structure
129  return MpduAggregator::GetSizeIfAggregated (mpdu->GetSize (), 0);
130  }
131  return mpdu->GetSize ();
132  }
133 
134  // aggregate the (A-)MSDU being built to the existing A-MPDU (if any)
135  uint32_t ampduSize = MpduAggregator::GetSizeIfAggregated (infoIt->second.header.GetSize ()
136  + infoIt->second.amsduSize
138  infoIt->second.ampduSize);
139  // aggregate the new MPDU to the A-MPDU
140  return MpduAggregator::GetSizeIfAggregated (mpdu->GetSize (), ampduSize);
141 }
142 
143 void
145 {
146  NS_LOG_FUNCTION (this << *msdu);
147 
148  auto infoIt = m_info.find (msdu->GetHeader ().GetAddr1 ());
149  NS_ASSERT_MSG (infoIt != m_info.end (),
150  "There must be already an MPDU addressed to the same receiver");
151 
152  infoIt->second.amsduSize = GetSizeIfAggregateMsdu (msdu).first;
153  infoIt->second.header.SetQosAmsdu ();
154 }
155 
156 std::pair<uint16_t, uint32_t>
158 {
159  NS_LOG_FUNCTION (this << *msdu);
160 
161  NS_ASSERT_MSG (msdu->GetHeader ().IsQosData (), "Can only aggregate a QoS data frame to an A-MSDU");
162 
163  auto infoIt = m_info.find (msdu->GetHeader ().GetAddr1 ());
164  NS_ASSERT_MSG (infoIt != m_info.end (),
165  "There must be already an MPDU addressed to the same receiver");
166 
167  NS_ASSERT_MSG (infoIt->second.amsduSize > 0,
168  "The amsduSize should be set to the size of the previous MSDU(s)");
169  NS_ASSERT_MSG (infoIt->second.header.IsQosData (),
170  "The MPDU being built for this receiver must be a QoS data frame");
171  NS_ASSERT_MSG (infoIt->second.header.GetQosTid () == msdu->GetHeader ().GetQosTid (),
172  "The MPDU being built must belong to the same TID as the MSDU to aggregate");
173  NS_ASSERT_MSG (infoIt->second.seqNumbers.find (msdu->GetHeader ().GetQosTid ()) != infoIt->second.seqNumbers.end (),
174  "At least one MPDU with the same TID must have been added previously");
175 
176  // all checks passed
177  uint16_t currAmsduSize = infoIt->second.amsduSize;
178 
179  if (!infoIt->second.header.IsQosAmsdu ())
180  {
181  // consider the A-MSDU subframe for the first MSDU
182  currAmsduSize = MsduAggregator::GetSizeIfAggregated (currAmsduSize, 0);
183  }
184 
185  uint16_t newAmsduSize = MsduAggregator::GetSizeIfAggregated (msdu->GetPacket ()->GetSize (), currAmsduSize);
186  uint32_t newMpduSize = infoIt->second.header.GetSize () + newAmsduSize + WIFI_MAC_FCS_LENGTH;
187 
188  if (infoIt->second.ampduSize > 0 || m_txVector.GetModulationClass () >= WIFI_MOD_CLASS_VHT)
189  {
190  return {newAmsduSize, MpduAggregator::GetSizeIfAggregated (newMpduSize, infoIt->second.ampduSize)};
191  }
192 
193  return {newAmsduSize, newMpduSize};
194 }
195 
196 uint32_t
198 {
199  NS_LOG_FUNCTION (this << receiver);
200 
201  auto infoIt = m_info.find (receiver);
202 
203  if (infoIt == m_info.end ())
204  {
205  return 0;
206  }
207 
208  uint32_t newMpduSize = infoIt->second.header.GetSize () + infoIt->second.amsduSize + WIFI_MAC_FCS_LENGTH;
209 
210  if (infoIt->second.ampduSize > 0 || m_txVector.GetModulationClass () >= WIFI_MOD_CLASS_VHT)
211  {
212  return MpduAggregator::GetSizeIfAggregated (newMpduSize, infoIt->second.ampduSize);
213  }
214 
215  return newMpduSize;
216 }
217 
218 void
219 WifiTxParameters::Print (std::ostream& os) const
220 {
221  os << "TXVECTOR=" << m_txVector;
222  if (m_protection)
223  {
224  os << ", Protection=" << m_protection.get ();
225  }
226  if (m_acknowledgment)
227  {
228  os << ", Acknowledgment=" << m_acknowledgment.get ();
229  }
230  os << ", PSDUs:";
231  for (const auto& info : m_info)
232  {
233  os << " [To=" << info.second.header.GetAddr1 () << ", A-MSDU size="
234  << info.second.amsduSize << ", A-MPDU size=" << info.second.ampduSize << "]";
235  }
236 }
237 
238 std::ostream & operator << (std::ostream &os, const WifiTxParameters* txParams)
239 {
240  txParams->Print (os);
241  return os;
242 }
243 
244 } //namespace ns3
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:274
std::unique_ptr< WifiProtection > m_protection
protection method
void AggregateMsdu(Ptr< const WifiMacQueueItem > msdu)
Record that an MSDU is being aggregated to the last MPDU added to the frame that hase the same receiv...
PsduInfoMap m_info
information about the frame being prepared.
void Clear(void)
Reset the TX parameters.
WifiModulationClass GetModulationClass(void) const
Get the modulation class specified by this TXVECTOR.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
static const uint16_t WIFI_MAC_FCS_LENGTH
The length in octects of the IEEE 802.11 MAC FCS field.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time m_txDuration
TX duration of the frame.
static uint32_t GetSizeIfAggregated(uint32_t mpduSize, uint32_t ampduSize)
Compute the size of the A-MPDU resulting from the aggregation of an MPDU of size mpduSize and an A-MP...
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:137
const PsduInfoMap & GetPsduInfoMap(void) const
Get a const reference to the map containing information about PSDUs.
void Print(std::ostream &os) const
Print the object contents.
const PsduInfo * GetPsduInfo(Mac48Address receiver) const
Get a pointer to the information about the PSDU addressed to the given receiver, if present...
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
static uint16_t GetSizeIfAggregated(uint16_t msduSize, uint16_t amsduSize)
Compute the size of the A-MSDU resulting from the aggregation of an MSDU of size msduSize and an A-MS...
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
std::pair< uint16_t, uint32_t > GetSizeIfAggregateMsdu(Ptr< const WifiMacQueueItem > msdu) const
Get the size in bytes of the frame in case the given MSDU is aggregated.
an EUI-48 address
Definition: mac48-address.h:43
information about the frame being prepared for a specific receiver
void AddMpdu(Ptr< const WifiMacQueueItem > mpdu)
Record that an MPDU is being added to the current frame.
uint32_t GetSize(Mac48Address receiver) const
Get the size in bytes of the (A-)MPDU addressed to the given receiver.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
uint32_t GetSizeIfAddMpdu(Ptr< const WifiMacQueueItem > mpdu) const
Get the size in bytes of the frame in case the given MPDU is added.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism...
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data...
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
std::map< Mac48Address, PsduInfo > PsduInfoMap
Map containing information about the PSDUs addressed to every receiver.
Implements the IEEE 802.11 MAC header.
bool HasData(void) const
Return true if the header type is DATA and is not DATA_NULL.