A Discrete-Event Network Simulator
API
wifi-psdu.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2019 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 "ns3/packet.h"
22 #include "ns3/log.h"
23 #include "wifi-mac-queue-item.h"
24 #include "wifi-psdu.h"
25 #include "wifi-mac-trailer.h"
26 #include "mpdu-aggregator.h"
27 #include "wifi-utils.h"
28 
29 namespace ns3 {
30 
31 NS_LOG_COMPONENT_DEFINE ("WifiPsdu");
32 
34  : m_isSingle (false)
35 {
36  m_mpduList.push_back (Create<WifiMacQueueItem> (p, header));
38 }
39 
41  : m_isSingle (isSingle)
42 {
43  m_mpduList.push_back (mpdu);
44  m_size = mpdu->GetSize ();
45 
46  if (isSingle)
47  {
48  m_size += 4; // A-MPDU Subframe header size
49  }
50 }
51 
53  : WifiPsdu (Create<WifiMacQueueItem> (*mpdu), isSingle)
54 {
55 }
56 
58  : m_isSingle (mpduList.size () == 1),
59  m_mpduList (mpduList)
60 {
61  NS_ABORT_MSG_IF (mpduList.empty (), "Cannot initialize a WifiPsdu with an empty MPDU list");
62 
63  m_size = 0;
64  for (auto& mpdu : m_mpduList)
65  {
67  }
68 }
69 
71 {
72 }
73 
74 bool
75 WifiPsdu::IsSingle (void) const
76 {
77  NS_LOG_FUNCTION (this);
78  return m_isSingle;
79 }
80 
81 bool
83 {
84  NS_LOG_FUNCTION (this);
85  return (m_mpduList.size () > 1 || m_isSingle);
86 }
87 
89 WifiPsdu::GetPacket (void) const
90 {
91  NS_LOG_FUNCTION (this);
92  Ptr<Packet> packet = Create<Packet> ();
93 
94  if (m_mpduList.size () == 1 && !m_isSingle)
95  {
96  packet = m_mpduList.at (0)->GetPacket ()->Copy ();
97  packet->AddHeader (m_mpduList.at (0)->GetHeader ());
98  AddWifiMacTrailer (packet);
99  }
100  else if (m_isSingle)
101  {
102  MpduAggregator::Aggregate (m_mpduList.at (0), packet, true);
103  }
104  else
105  {
106  for (auto& mpdu : m_mpduList)
107  {
108  MpduAggregator::Aggregate (mpdu, packet, false);
109  }
110  }
111  return packet;
112 }
113 
115 WifiPsdu::GetAddr1 (void) const
116 {
117  NS_LOG_FUNCTION (this);
118  Mac48Address ra = m_mpduList.at (0)->GetHeader ().GetAddr1 ();
119 
120  // check that the other MPDUs have the same RA
121  for (std::size_t i = 1; i < m_mpduList.size (); i++)
122  {
123  if (m_mpduList.at (i)->GetHeader ().GetAddr1 () != ra)
124  {
125  NS_ABORT_MSG ("MPDUs in an A-AMPDU must have the same receiver address");
126  }
127  }
128  return ra;
129 }
130 
132 WifiPsdu::GetAddr2 (void) const
133 {
134  NS_LOG_FUNCTION (this);
135  Mac48Address ta = m_mpduList.at (0)->GetHeader ().GetAddr2 ();
136 
137  // check that the other MPDUs have the same TA
138  for (std::size_t i = 1; i < m_mpduList.size (); i++)
139  {
140  if (m_mpduList.at (i)->GetHeader ().GetAddr2 () != ta)
141  {
142  NS_ABORT_MSG ("MPDUs in an A-AMPDU must have the same transmitter address");
143  }
144  }
145  return ta;
146 }
147 
148 Time
150 {
151  NS_LOG_FUNCTION (this);
152  Time duration = m_mpduList.at (0)->GetHeader ().GetDuration ();
153 
154  // check that the other MPDUs have the same Duration/ID
155  for (std::size_t i = 1; i < m_mpduList.size (); i++)
156  {
157  if (m_mpduList.at (i)->GetHeader ().GetDuration () != duration)
158  {
159  NS_ABORT_MSG ("MPDUs in an A-AMPDU must have the same Duration/ID");
160  }
161  }
162  return duration;
163 }
164 
165 void
167 {
168  NS_LOG_FUNCTION (this << duration);
169 
170  for (auto& mpdu : m_mpduList)
171  {
172  mpdu->GetHeader ().SetDuration (duration);
173  }
174 }
175 
176 std::set<uint8_t>
177 WifiPsdu::GetTids (void) const
178 {
179  NS_LOG_FUNCTION (this);
180 
181  std::set<uint8_t> s;
182  for (auto& mpdu : m_mpduList)
183  {
184  if (mpdu->GetHeader ().IsQosData ())
185  {
186  s.insert (mpdu->GetHeader ().GetQosTid ());
187  }
188  }
189  return s;
190 }
191 
193 WifiPsdu::GetAckPolicyForTid (uint8_t tid) const
194 {
195  NS_LOG_FUNCTION (this << +tid);
197  auto it = m_mpduList.begin ();
198  bool found = false;
199 
200  // find the first QoS Data frame with the given TID
201  do
202  {
203  if ((*it)->GetHeader ().IsQosData () && (*it)->GetHeader ().GetQosTid () == tid)
204  {
205  policy = (*it)->GetHeader ().GetQosAckPolicy ();
206  found = true;
207  }
208  it++;
209  } while (!found && it != m_mpduList.end ());
210 
211  NS_ABORT_MSG_IF (!found, "No QoS Data frame in the PSDU");
212 
213  // check that the other QoS Data frames with the given TID have the same ack policy
214  while (it != m_mpduList.end ())
215  {
216  if ((*it)->GetHeader ().IsQosData () && (*it)->GetHeader ().GetQosTid () == tid
217  && (*it)->GetHeader ().GetQosAckPolicy () != policy)
218  {
219  NS_ABORT_MSG ("QoS Data frames with the same TID must have the same QoS Ack Policy");
220  }
221  it++;
222  }
223  return policy;
224 }
225 
226 void
228 {
229  NS_LOG_FUNCTION (this << +tid << policy);
230 
231  for (auto& mpdu : m_mpduList)
232  {
233  if (mpdu->GetHeader ().IsQosData () && mpdu->GetHeader ().GetQosTid () == tid)
234  {
235  mpdu->GetHeader ().SetQosAckPolicy (policy);
236  }
237  }
238 }
239 
240 uint32_t
241 WifiPsdu::GetSize (void) const
242 {
243  NS_LOG_FUNCTION (this);
244  return m_size;
245 }
246 
247 const WifiMacHeader &
248 WifiPsdu::GetHeader (std::size_t i) const
249 {
250  NS_LOG_FUNCTION (this << i);
251  return m_mpduList.at (i)->GetHeader ();
252 }
253 
255 WifiPsdu::GetHeader (std::size_t i)
256 {
257  NS_LOG_FUNCTION (this << i);
258  return m_mpduList.at (i)->GetHeader ();
259 }
260 
262 WifiPsdu::GetPayload (std::size_t i) const
263 {
264  NS_LOG_FUNCTION (this << i);
265  return m_mpduList.at (i)->GetPacket ();
266 }
267 
268 Time
269 WifiPsdu::GetTimeStamp (std::size_t i) const
270 {
271  NS_LOG_FUNCTION (this << i);
272  return m_mpduList.at (i)->GetTimeStamp ();
273 }
274 
275 std::size_t
277 {
278  NS_LOG_FUNCTION (this);
279  return m_mpduList.size ();
280 }
281 
282 std::vector<Ptr<WifiMacQueueItem>>::const_iterator
283 WifiPsdu::begin (void) const
284 {
285  NS_LOG_FUNCTION (this);
286  return m_mpduList.begin ();
287 }
288 
289 std::vector<Ptr<WifiMacQueueItem>>::iterator
291 {
292  NS_LOG_FUNCTION (this);
293  return m_mpduList.begin ();
294 }
295 
296 std::vector<Ptr<WifiMacQueueItem>>::const_iterator
297 WifiPsdu::end (void) const
298 {
299  NS_LOG_FUNCTION (this);
300  return m_mpduList.end ();
301 }
302 
303 std::vector<Ptr<WifiMacQueueItem>>::iterator
305 {
306  NS_LOG_FUNCTION (this);
307  return m_mpduList.end ();
308 }
309 
310 } //namespace ns3
bool IsSingle(void) const
Return true if the PSDU is an S-MPDU.
Definition: wifi-psdu.cc:75
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
WifiPsdu(Ptr< const Packet > p, const WifiMacHeader &header)
Create a PSDU storing an MPDU.
Definition: wifi-psdu.cc:33
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
void SetDuration(Time duration)
Set the Duration/ID field on all the MPDUs.
Definition: wifi-psdu.cc:166
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
void AddWifiMacTrailer(Ptr< Packet > packet)
Add FCS trailer to a packet.
Definition: wifi-utils.cc:221
Time GetTimeStamp(std::size_t i) const
Get the timestamp of the i-th MPDU.
Definition: wifi-psdu.cc:269
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:204
std::vector< Ptr< WifiMacQueueItem > >::const_iterator end(void) const
Return a const iterator to past-the-last MPDU.
Definition: wifi-psdu.cc:297
bool m_isSingle
true for an S-MPDU
Definition: wifi-psdu.h:218
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...
uint32_t GetSize(void) const
Return the size of the PSDU.
Definition: wifi-psdu.cc:241
Ptr< const Packet > GetPacket(void) const
Get the PSDU as a single packet.
Definition: wifi-psdu.cc:89
WifiMacQueueItem stores (const) packets along with their Wifi MAC headers and the time when they were...
void SetAckPolicyForTid(uint8_t tid, WifiMacHeader::QosAckPolicy policy)
Set the QoS Ack Policy of the QoS Data frames included in the PSDU that have the given TID to the giv...
Definition: wifi-psdu.cc:227
Time GetDuration(void) const
Get the duration from the Duration/ID field, which is common to all the MPDUs.
Definition: wifi-psdu.cc:149
Mac48Address GetAddr2(void) const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:132
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:248
static void Aggregate(Ptr< const WifiMacQueueItem > mpdu, Ptr< Packet > ampdu, bool isSingle)
Aggregate an MPDU to an A-MPDU.
WifiPsdu stores an MPDU, S-MPDU or A-MPDU, by keeping header(s) and payload(s) separate for each cons...
Definition: wifi-psdu.h:40
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:276
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::set< uint8_t > GetTids(void) const
Get the set of TIDs of the QoS Data frames included in the PSDU.
Definition: wifi-psdu.cc:177
an EUI-48 address
Definition: mac48-address.h:43
Ptr< T > Create(void)
Create class instances by constructors with varying numbers of arguments and return them by Ptr...
Definition: ptr.h:516
QosAckPolicy
ACK policy for QoS frames.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
uint32_t m_size
the size of the PSDU
Definition: wifi-psdu.h:220
uint32_t GetSerializedSize(void) const
std::vector< Ptr< WifiMacQueueItem > >::const_iterator begin(void) const
Return a const iterator to the first MPDU.
Definition: wifi-psdu.cc:283
virtual ~WifiPsdu()
Definition: wifi-psdu.cc:70
Mac48Address GetAddr1(void) const
Get the Receiver Address (RA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:115
std::vector< Ptr< WifiMacQueueItem > > m_mpduList
list of constituent MPDUs
Definition: wifi-psdu.h:219
Ptr< const Packet > GetPayload(std::size_t i) const
Get the payload of the i-th MPDU.
Definition: wifi-psdu.cc:262
WifiMacHeader::QosAckPolicy GetAckPolicyForTid(uint8_t tid) const
Get the QoS Ack Policy of the QoS Data frames included in the PSDU that have the given TID...
Definition: wifi-psdu.cc:193
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
Implements the IEEE 802.11 MAC header.
bool IsAggregate(void) const
Return true if the PSDU is an S-MPDU or A-MPDU.
Definition: wifi-psdu.cc:82