A Discrete-Event Network Simulator
API
vht-ppdu.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Orange Labs
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Rediet <getachew.redieteab@orange.com>
18  * Muhammad Iqbal Rochman <muhiqbalcr@uchicago.edu>
19  * Sébastien Deronne <sebastien.deronne@gmail.com> (VhtSigHeader)
20  */
21 
22 #include "vht-ppdu.h"
23 
24 #include "vht-phy.h"
25 
26 #include "ns3/log.h"
27 #include "ns3/wifi-phy.h"
28 #include "ns3/wifi-psdu.h"
29 
30 namespace ns3
31 {
32 
33 NS_LOG_COMPONENT_DEFINE("VhtPpdu");
34 
36  const WifiTxVector& txVector,
37  uint16_t txCenterFreq,
38  Time ppduDuration,
39  WifiPhyBand band,
40  uint64_t uid)
41  : OfdmPpdu(psdu,
42  txVector,
43  txCenterFreq,
44  band,
45  uid,
46  false) // don't instantiate LSigHeader of OfdmPpdu
47 {
48  NS_LOG_FUNCTION(this << psdu << txVector << txCenterFreq << ppduDuration << band << uid);
49  SetPhyHeaders(txVector, ppduDuration);
50 }
51 
52 void
53 VhtPpdu::SetPhyHeaders(const WifiTxVector& txVector, Time ppduDuration)
54 {
55  NS_LOG_FUNCTION(this << txVector << ppduDuration);
56 
57 #ifdef NS3_BUILD_PROFILE_DEBUG
58  LSigHeader lSig;
59  SetLSigHeader(lSig, ppduDuration);
60 
61  VhtSigHeader vhtSig;
62  SetVhtSigHeader(vhtSig, txVector, ppduDuration);
63 
64  m_phyHeaders->AddHeader(vhtSig);
65  m_phyHeaders->AddHeader(lSig);
66 #else
67  SetLSigHeader(m_lSig, ppduDuration);
68  SetVhtSigHeader(m_vhtSig, txVector, ppduDuration);
69 #endif
70 }
71 
72 void
73 VhtPpdu::SetLSigHeader(LSigHeader& lSig, Time ppduDuration) const
74 {
75  uint16_t length =
76  ((ceil((static_cast<double>(ppduDuration.GetNanoSeconds() - (20 * 1000)) / 1000) / 4.0) *
77  3) -
78  3);
79  lSig.SetLength(length);
80 }
81 
82 void
84  const WifiTxVector& txVector,
85  Time ppduDuration) const
86 {
88  vhtSig.SetChannelWidth(txVector.GetChannelWidth());
89  vhtSig.SetShortGuardInterval(txVector.GetGuardInterval() == 400);
90  uint32_t nSymbols =
91  (static_cast<double>(
92  (ppduDuration - WifiPhy::CalculatePhyPreambleAndHeaderDuration(txVector))
93  .GetNanoSeconds()) /
94  (3200 + txVector.GetGuardInterval()));
95  if (txVector.GetGuardInterval() == 400)
96  {
97  vhtSig.SetShortGuardIntervalDisambiguation((nSymbols % 10) == 9);
98  }
99  vhtSig.SetSuMcs(txVector.GetMode().GetMcsValue());
100  vhtSig.SetNStreams(txVector.GetNss());
101 }
102 
105 {
106  WifiTxVector txVector;
107  txVector.SetPreambleType(m_preamble);
108 
109 #ifdef NS3_BUILD_PROFILE_DEBUG
110  auto phyHeaders = m_phyHeaders->Copy();
111 
112  LSigHeader lSig;
113  if (phyHeaders->RemoveHeader(lSig) == 0)
114  {
115  NS_FATAL_ERROR("Missing L-SIG header in VHT PPDU");
116  }
117 
118  VhtSigHeader vhtSig;
119  if (phyHeaders->RemoveHeader(vhtSig) == 0)
120  {
121  NS_FATAL_ERROR("Missing VHT-SIG header in VHT PPDU");
122  }
123 
124  SetTxVectorFromPhyHeaders(txVector, lSig, vhtSig);
125 #else
126  SetTxVectorFromPhyHeaders(txVector, m_lSig, m_vhtSig);
127 #endif
128 
129  return txVector;
130 }
131 
132 void
134  const LSigHeader& lSig,
135  const VhtSigHeader& vhtSig) const
136 {
137  txVector.SetMode(VhtPhy::GetVhtMcs(vhtSig.GetSuMcs()));
138  txVector.SetChannelWidth(vhtSig.GetChannelWidth());
139  txVector.SetNss(vhtSig.GetNStreams());
140  txVector.SetGuardInterval(vhtSig.GetShortGuardInterval() ? 400 : 800);
141  txVector.SetAggregation(GetPsdu()->IsAggregate());
142 }
143 
144 Time
146 {
147  Time ppduDuration = Seconds(0);
148  const WifiTxVector& txVector = GetTxVector();
149 
150  uint16_t length = 0;
151  bool sgi = false;
152  bool sgiDisambiguation = false;
153 #ifdef NS3_BUILD_PROFILE_DEBUG
154  auto phyHeaders = m_phyHeaders->Copy();
155 
156  LSigHeader lSig;
157  phyHeaders->RemoveHeader(lSig);
158  VhtSigHeader vhtSig;
159  phyHeaders->RemoveHeader(vhtSig);
160 
161  length = lSig.GetLength();
162  sgi = vhtSig.GetShortGuardInterval();
163  sgiDisambiguation = vhtSig.GetShortGuardIntervalDisambiguation();
164 #else
165  length = m_lSig.GetLength();
166  sgi = m_vhtSig.GetShortGuardInterval();
167  sgiDisambiguation = m_vhtSig.GetShortGuardIntervalDisambiguation();
168 #endif
169 
170  Time tSymbol = NanoSeconds(3200 + txVector.GetGuardInterval());
171  Time preambleDuration = WifiPhy::CalculatePhyPreambleAndHeaderDuration(txVector);
172  Time calculatedDuration = MicroSeconds(((ceil(static_cast<double>(length + 3) / 3)) * 4) + 20);
173  uint32_t nSymbols =
174  floor(static_cast<double>((calculatedDuration - preambleDuration).GetNanoSeconds()) /
175  tSymbol.GetNanoSeconds());
176  if (sgi && sgiDisambiguation)
177  {
178  nSymbols--;
179  }
180  ppduDuration = preambleDuration + (nSymbols * tSymbol);
181  return ppduDuration;
182 }
183 
186 {
187  return Ptr<WifiPpdu>(new VhtPpdu(*this), false);
188 }
189 
192 {
194 }
195 
197  : m_bw(0),
198  m_nsts(0),
199  m_sgi(0),
200  m_sgi_disambiguation(0),
201  m_suMcs(0),
202  m_mu(false)
203 {
204 }
205 
206 TypeId
208 {
209  static TypeId tid = TypeId("ns3::VhtSigHeader")
210  .SetParent<Header>()
211  .SetGroupName("Wifi")
212  .AddConstructor<VhtSigHeader>();
213  return tid;
214 }
215 
216 TypeId
218 {
219  return GetTypeId();
220 }
221 
222 void
223 VhtPpdu::VhtSigHeader::Print(std::ostream& os) const
224 {
225  os << "SU_MCS=" << +m_suMcs << " CHANNEL_WIDTH=" << GetChannelWidth() << " SGI=" << +m_sgi
226  << " NSTS=" << +m_nsts << " MU=" << +m_mu;
227 }
228 
229 uint32_t
231 {
232  uint32_t size = 0;
233  size += 3; // VHT-SIG-A1
234  size += 3; // VHT-SIG-A2
235  if (m_mu)
236  {
237  size += 4; // VHT-SIG-B
238  }
239  return size;
240 }
241 
242 void
244 {
245  m_mu = mu;
246 }
247 
248 void
250 {
251  if (channelWidth == 160)
252  {
253  m_bw = 3;
254  }
255  else if (channelWidth == 80)
256  {
257  m_bw = 2;
258  }
259  else if (channelWidth == 40)
260  {
261  m_bw = 1;
262  }
263  else
264  {
265  m_bw = 0;
266  }
267 }
268 
269 uint16_t
271 {
272  if (m_bw == 3)
273  {
274  return 160;
275  }
276  else if (m_bw == 2)
277  {
278  return 80;
279  }
280  else if (m_bw == 1)
281  {
282  return 40;
283  }
284  else
285  {
286  return 20;
287  }
288 }
289 
290 void
292 {
293  NS_ASSERT(nStreams <= 8);
294  m_nsts = (nStreams - 1);
295 }
296 
297 uint8_t
299 {
300  return (m_nsts + 1);
301 }
302 
303 void
305 {
306  m_sgi = sgi ? 1 : 0;
307 }
308 
309 bool
311 {
312  return m_sgi;
313 }
314 
315 void
317 {
318  m_sgi_disambiguation = disambiguation ? 1 : 0;
319 }
320 
321 bool
323 {
324  return m_sgi_disambiguation;
325 }
326 
327 void
329 {
330  NS_ASSERT(mcs <= 9);
331  m_suMcs = mcs;
332 }
333 
334 uint8_t
336 {
337  return m_suMcs;
338 }
339 
340 void
342 {
343  // VHT-SIG-A1
344  uint8_t byte = m_bw;
345  byte |= (0x01 << 2); // Set Reserved bit #2 to 1
346  start.WriteU8(byte);
347  uint16_t bytes = (m_nsts & 0x07) << 2;
348  bytes |= (0x01 << (23 - 8)); // Set Reserved bit #23 to 1
349  start.WriteU16(bytes);
350 
351  // VHT-SIG-A2
352  byte = m_sgi & 0x01;
353  byte |= ((m_sgi_disambiguation & 0x01) << 1);
354  byte |= ((m_suMcs & 0x0f) << 4);
355  start.WriteU8(byte);
356  bytes = (0x01 << (9 - 8)); // Set Reserved bit #9 to 1
357  start.WriteU16(bytes);
358 
359  if (m_mu)
360  {
361  // VHT-SIG-B
362  start.WriteU32(0);
363  }
364 }
365 
366 uint32_t
368 {
370 
371  // VHT-SIG-A1
372  uint8_t byte = i.ReadU8();
373  m_bw = byte & 0x03;
374  uint16_t bytes = i.ReadU16();
375  m_nsts = ((bytes >> 2) & 0x07);
376 
377  // VHT-SIG-A2
378  byte = i.ReadU8();
379  m_sgi = byte & 0x01;
380  m_sgi_disambiguation = ((byte >> 1) & 0x01);
381  m_suMcs = ((byte >> 4) & 0x0f);
382  i.ReadU16();
383 
384  if (m_mu)
385  {
386  // VHT-SIG-B
387  i.ReadU32();
388  }
389 
390  return i.GetDistanceFrom(start);
391 }
392 
393 } // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint8_t ReadU8()
Definition: buffer.h:1027
uint32_t ReadU32()
Definition: buffer.cc:969
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:783
uint16_t ReadU16()
Definition: buffer.h:1035
Protocol header serialization and deserialization.
Definition: header.h:44
virtual uint32_t Deserialize(Buffer::Iterator start)=0
Deserialize the object from a buffer iterator.
OFDM and ERP OFDM L-SIG PHY header.
Definition: ofdm-ppdu.h:55
uint16_t GetLength() const
Return the LENGTH field of L-SIG (in bytes).
Definition: ofdm-ppdu.cc:264
void SetLength(uint16_t length)
Fill the LENGTH field of L-SIG (in bytes).
Definition: ofdm-ppdu.cc:257
OFDM PPDU (11a)
Definition: ofdm-ppdu.h:48
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:417
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
static WifiMode GetVhtMcs(uint8_t index)
Return the VHT MCS corresponding to the provided index.
Definition: vht-phy.cc:344
VHT PHY header (VHT-SIG-A1/A2/B).
Definition: vht-ppdu.h:52
static TypeId GetTypeId()
Get the type ID.
Definition: vht-ppdu.cc:207
void SetNStreams(uint8_t nStreams)
Fill the number of streams field of VHT-SIG-A1.
Definition: vht-ppdu.cc:291
void SetChannelWidth(uint16_t channelWidth)
Fill the channel width field of VHT-SIG-A1 (in MHz).
Definition: vht-ppdu.cc:249
uint16_t GetChannelWidth() const
Return the channel width (in MHz).
Definition: vht-ppdu.cc:270
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: vht-ppdu.cc:217
uint8_t GetSuMcs() const
Return the SU VHT MCS field of VHT-SIG-A2.
Definition: vht-ppdu.cc:335
uint8_t GetNStreams() const
Return the number of streams.
Definition: vht-ppdu.cc:298
bool GetShortGuardInterval() const
Return the short GI field of VHT-SIG-A2.
Definition: vht-ppdu.cc:310
void Serialize(Buffer::Iterator start) const override
Definition: vht-ppdu.cc:341
void SetMuFlag(bool mu)
Set the Multi-User (MU) flag.
Definition: vht-ppdu.cc:243
void SetSuMcs(uint8_t mcs)
Fill the SU VHT MCS field of VHT-SIG-A2.
Definition: vht-ppdu.cc:328
void SetShortGuardIntervalDisambiguation(bool disambiguation)
Fill the short GI NSYM disambiguation field of VHT-SIG-A2.
Definition: vht-ppdu.cc:316
bool GetShortGuardIntervalDisambiguation() const
Return the short GI NSYM disambiguation field of VHT-SIG-A2.
Definition: vht-ppdu.cc:322
uint32_t GetSerializedSize() const override
Definition: vht-ppdu.cc:230
void SetShortGuardInterval(bool sgi)
Fill the short guard interval field of VHT-SIG-A2.
Definition: vht-ppdu.cc:304
void Print(std::ostream &os) const override
Definition: vht-ppdu.cc:223
virtual void SetPhyHeaders(const WifiTxVector &txVector, Time ppduDuration)
Fill in the PHY headers.
Definition: vht-ppdu.cc:53
VhtPpdu(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint16_t txCenterFreq, Time ppduDuration, WifiPhyBand band, uint64_t uid)
Create a VHT PPDU.
Definition: vht-ppdu.cc:35
WifiPpduType GetType() const override
Return the PPDU type (.
Definition: vht-ppdu.cc:191
WifiTxVector DoGetTxVector() const override
Get the TXVECTOR used to send the PPDU.
Definition: vht-ppdu.cc:104
void SetTxVectorFromPhyHeaders(WifiTxVector &txVector, const LSigHeader &lSig, const VhtSigHeader &vhtSig) const
Fill in the TXVECTOR from PHY headers.
Definition: vht-ppdu.cc:133
void SetVhtSigHeader(VhtSigHeader &vhtSig, const WifiTxVector &txVector, Time ppduDuration) const
Fill in the VHT-SIG header.
Definition: vht-ppdu.cc:83
Time GetTxDuration() const override
Get the total transmission duration of the PPDU.
Definition: vht-ppdu.cc:145
Ptr< WifiPpdu > Copy() const override
Copy this instance.
Definition: vht-ppdu.cc:185
virtual void SetLSigHeader(LSigHeader &lSig, Time ppduDuration) const
Fill in the L-SIG header.
Definition: vht-ppdu.cc:73
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1473
WifiPreamble m_preamble
the PHY preamble
Definition: wifi-ppdu.h:201
Ptr< const WifiPsdu > GetPsdu() const
Get the payload of the PPDU.
Definition: wifi-ppdu.cc:117
const WifiTxVector & GetTxVector() const
Get the TXVECTOR used to send the PPDU.
Definition: wifi-ppdu.cc:82
Ptr< Packet > m_phyHeaders
the PHY headers contained in this PPDU
Definition: wifi-ppdu.h:211
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint16_t GetGuardInterval() const
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
uint16_t GetChannelWidth() const
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
WifiPpduType
The type of PPDU (SU, DL MU, or UL MU)
@ WIFI_PREAMBLE_VHT_MU
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_PPDU_TYPE_SU
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Declaration of ns3::VhtPhy class.
Declaration of ns3::VhtPpdu class.