A Discrete-Event Network Simulator
API
he-ppdu.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 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> (HeSigHeader)
20  */
21 
22 #include "he-ppdu.h"
23 
24 #include "he-phy.h"
25 
26 #include "ns3/log.h"
27 #include "ns3/wifi-phy.h"
28 #include "ns3/wifi-psdu.h"
29 #include "ns3/wifi-utils.h"
30 
31 namespace ns3
32 {
33 
34 NS_LOG_COMPONENT_DEFINE("HePpdu");
35 
36 std::ostream&
37 operator<<(std::ostream& os, const HePpdu::TxPsdFlag& flag)
38 {
39  switch (flag)
40  {
42  return (os << "PSD_NON_HE_PORTION");
44  return (os << "PSD_HE_PORTION");
45  default:
46  NS_FATAL_ERROR("Invalid PSD flag");
47  return (os << "INVALID");
48  }
49 }
50 
52  const WifiTxVector& txVector,
53  uint16_t txCenterFreq,
54  Time ppduDuration,
55  WifiPhyBand band,
56  uint64_t uid,
57  TxPsdFlag flag)
58  : OfdmPpdu(psdus.begin()->second,
59  txVector,
60  txCenterFreq,
61  band,
62  uid,
63  false) // don't instantiate LSigHeader of OfdmPpdu
64 {
65  NS_LOG_FUNCTION(this << psdus << txVector << txCenterFreq << ppduDuration << band << uid
66  << flag);
67 
68  // overwrite with map (since only first element used by OfdmPpdu)
69  m_psdus.begin()->second = nullptr;
70  m_psdus.clear();
71  m_psdus = psdus;
72  if (txVector.IsMu())
73  {
74  for (const auto& heMuUserInfo : txVector.GetHeMuUserInfoMap())
75  {
76  auto [it, ret] = m_muUserInfos.emplace(heMuUserInfo);
77  NS_ABORT_MSG_IF(!ret, "STA-ID " << heMuUserInfo.first << " already present");
78  }
80  m_ruAllocation = txVector.GetRuAllocation();
81  }
82  SetPhyHeaders(txVector, ppduDuration);
83  SetTxPsdFlag(flag);
84 }
85 
87  const WifiTxVector& txVector,
88  uint16_t txCenterFreq,
89  Time ppduDuration,
90  WifiPhyBand band,
91  uint64_t uid)
92  : OfdmPpdu(psdu,
93  txVector,
94  txCenterFreq,
95  band,
96  uid,
97  false) // don't instantiate LSigHeader of OfdmPpdu
98 {
99  NS_LOG_FUNCTION(this << psdu << txVector << txCenterFreq << ppduDuration << band << uid);
100  NS_ASSERT(!IsMu());
101  SetPhyHeaders(txVector, ppduDuration);
103 }
104 
105 void
106 HePpdu::SetPhyHeaders(const WifiTxVector& txVector, Time ppduDuration)
107 {
108  NS_LOG_FUNCTION(this << txVector << ppduDuration);
109 
110 #ifdef NS3_BUILD_PROFILE_DEBUG
111  LSigHeader lSig;
112  SetLSigHeader(lSig, ppduDuration);
113 
114  HeSigHeader heSig;
115  SetHeSigHeader(heSig, txVector);
116 
117  m_phyHeaders->AddHeader(heSig);
118  m_phyHeaders->AddHeader(lSig);
119 #else
120  SetLSigHeader(m_lSig, ppduDuration);
121  SetHeSigHeader(m_heSig, txVector);
122 #endif
123 }
124 
125 void
126 HePpdu::SetLSigHeader(LSigHeader& lSig, Time ppduDuration) const
127 {
128  uint8_t sigExtension = 0;
130  {
131  sigExtension = 6;
132  }
133  uint8_t m = IsDlMu() ? 1 : 2;
134  uint16_t length = ((ceil((static_cast<double>(ppduDuration.GetNanoSeconds() - (20 * 1000) -
135  (sigExtension * 1000)) /
136  1000) /
137  4.0) *
138  3) -
139  3 - m);
140  lSig.SetLength(length);
141 }
142 
143 void
144 HePpdu::SetHeSigHeader(HeSigHeader& heSig, const WifiTxVector& txVector) const
145 {
146  if (ns3::IsDlMu(m_preamble))
147  {
148  heSig.SetMuFlag(true);
149  heSig.SetMcs(txVector.GetSigBMode().GetMcsValue());
150  }
151  else if (!ns3::IsUlMu(m_preamble))
152  {
153  heSig.SetMcs(txVector.GetMode().GetMcsValue());
154  heSig.SetNStreams(txVector.GetNss());
155  }
156  heSig.SetBssColor(txVector.GetBssColor());
157  heSig.SetChannelWidth(txVector.GetChannelWidth());
158  if (!txVector.IsUlMu())
159  {
160  heSig.SetGuardIntervalAndLtfSize(txVector.GetGuardInterval(), 2 /*NLTF currently unused*/);
161  }
162 }
163 
166 {
167  WifiTxVector txVector;
168  txVector.SetPreambleType(m_preamble);
169 
170 #ifdef NS3_BUILD_PROFILE_DEBUG
171  auto phyHeaders = m_phyHeaders->Copy();
172 
173  LSigHeader lSig;
174  if (phyHeaders->RemoveHeader(lSig) == 0)
175  {
176  NS_FATAL_ERROR("Missing L-SIG header in HE PPDU");
177  }
178 
179  HeSigHeader heSig;
180  if (phyHeaders->PeekHeader(heSig) == 0)
181  {
182  NS_FATAL_ERROR("Missing HE-SIG header in HE PPDU");
183  }
184 
185  SetTxVectorFromPhyHeaders(txVector, lSig, heSig);
186 #else
187  SetTxVectorFromPhyHeaders(txVector, m_lSig, m_heSig);
188 #endif
189 
190  return txVector;
191 }
192 
193 void
195  const LSigHeader& lSig,
196  const HeSigHeader& heSig) const
197 {
198  txVector.SetChannelWidth(heSig.GetChannelWidth());
199  txVector.SetBssColor(heSig.GetBssColor());
200  txVector.SetLength(lSig.GetLength());
201  txVector.SetAggregation(m_psdus.size() > 1 || m_psdus.begin()->second->IsAggregate());
202  if (!IsMu())
203  {
204  txVector.SetMode(HePhy::GetHeMcs(heSig.GetMcs()));
205  txVector.SetNss(heSig.GetNStreams());
206  }
207  if (!IsUlMu())
208  {
209  txVector.SetGuardInterval(heSig.GetGuardInterval());
210  }
211  if (IsDlMu())
212  {
213  for (const auto& muUserInfo : m_muUserInfos)
214  {
215  txVector.SetHeMuUserInfo(muUserInfo.first, muUserInfo.second);
216  }
217  }
218  if (txVector.IsDlMu())
219  {
220  txVector.SetSigBMode(HePhy::GetVhtMcs(heSig.GetMcs()));
222  }
223 }
224 
225 Time
227 {
228  Time ppduDuration = Seconds(0);
229  const WifiTxVector& txVector = GetTxVector();
230 
231  uint16_t length = 0;
232 #ifdef NS3_BUILD_PROFILE_DEBUG
233  LSigHeader lSig;
234  m_phyHeaders->PeekHeader(lSig);
235  length = lSig.GetLength();
236 #else
237  length = m_lSig.GetLength();
238 #endif
239 
240  Time tSymbol = NanoSeconds(12800 + txVector.GetGuardInterval());
241  Time preambleDuration = WifiPhy::CalculatePhyPreambleAndHeaderDuration(txVector);
242  uint8_t sigExtension = 0;
244  {
245  sigExtension = 6;
246  }
247  uint8_t m = IsDlMu() ? 1 : 2;
248  // Equation 27-11 of IEEE P802.11ax/D4.0
249  Time calculatedDuration =
250  MicroSeconds(((ceil(static_cast<double>(length + 3 + m) / 3)) * 4) + 20 + sigExtension);
251  NS_ASSERT(calculatedDuration > preambleDuration);
252  uint32_t nSymbols =
253  floor(static_cast<double>((calculatedDuration - preambleDuration).GetNanoSeconds() -
254  (sigExtension * 1000)) /
255  tSymbol.GetNanoSeconds());
256  ppduDuration = preambleDuration + (nSymbols * tSymbol) + MicroSeconds(sigExtension);
257  return ppduDuration;
258 }
259 
262 {
263  return Ptr<WifiPpdu>(new HePpdu(*this), false);
264 }
265 
268 {
269  switch (m_preamble)
270  {
271  case WIFI_PREAMBLE_HE_MU:
272  return WIFI_PPDU_TYPE_DL_MU;
273  case WIFI_PREAMBLE_HE_TB:
274  return WIFI_PPDU_TYPE_UL_MU;
275  default:
276  return WIFI_PPDU_TYPE_SU;
277  }
278 }
279 
280 bool
282 {
283  return (IsDlMu() || IsUlMu());
284 }
285 
286 bool
288 {
289  return (m_preamble == WIFI_PREAMBLE_HE_MU);
290 }
291 
292 bool
294 {
295  return (m_preamble == WIFI_PREAMBLE_HE_TB);
296 }
297 
299 HePpdu::GetPsdu(uint8_t bssColor, uint16_t staId /* = SU_STA_ID */) const
300 {
301  if (!IsMu())
302  {
303  NS_ASSERT(m_psdus.size() == 1);
304  return m_psdus.at(SU_STA_ID);
305  }
306 
307  uint8_t ppduBssColor = 0;
308 #ifdef NS3_BUILD_PROFILE_DEBUG
309  auto phyHeaders = m_phyHeaders->Copy();
310  LSigHeader lSig;
311  phyHeaders->RemoveHeader(lSig);
312  HeSigHeader heSig;
313  phyHeaders->RemoveHeader(heSig);
314  ppduBssColor = heSig.GetBssColor();
315 #else
316  ppduBssColor = m_heSig.GetBssColor();
317 #endif
318 
319  if (IsUlMu())
320  {
321  NS_ASSERT(m_psdus.size() == 1);
322  if (bssColor == 0 || ppduBssColor == 0 || (bssColor == ppduBssColor))
323  {
324  return m_psdus.cbegin()->second;
325  }
326  }
327  else
328  {
329  if (bssColor == 0 || ppduBssColor == 0 || (bssColor == ppduBssColor))
330  {
331  const auto it = m_psdus.find(staId);
332  if (it != m_psdus.cend())
333  {
334  return it->second;
335  }
336  }
337  }
338  return nullptr;
339 }
340 
341 uint16_t
343 {
344  NS_ASSERT(IsUlMu());
345  return m_psdus.begin()->first;
346 }
347 
348 uint16_t
350 {
351  const WifiTxVector& txVector = GetTxVector();
352  if (txVector.IsUlMu() && GetStaId() != SU_STA_ID)
353  {
354  TxPsdFlag flag = GetTxPsdFlag();
355  uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(GetStaId()).GetRuType());
356  uint16_t channelWidth = (flag == PSD_NON_HE_PORTION && ruWidth < 20) ? 20 : ruWidth;
357  NS_LOG_INFO("Use channelWidth=" << channelWidth << " MHz for HE TB from " << GetStaId()
358  << " for " << flag);
359  return channelWidth;
360  }
361  else
362  {
364  }
365 }
366 
369 {
370  return m_txPsdFlag;
371 }
372 
373 void
375 {
376  NS_LOG_FUNCTION(this << flag);
377  m_txPsdFlag = flag;
378 }
379 
380 void
381 HePpdu::UpdateTxVectorForUlMu(const std::optional<WifiTxVector>& trigVector) const
382 {
383  if (trigVector.has_value())
384  {
385  NS_LOG_FUNCTION(this << trigVector.value());
386  }
387  else
388  {
389  NS_LOG_FUNCTION(this);
390  }
391  if (!m_txVector.has_value())
392  {
394  }
397  // HE TB PPDU reception needs information from the TRIGVECTOR to be able to receive the PPDU
398  const auto staId = GetStaId();
399  if (trigVector.has_value() && trigVector->IsUlMu() &&
400  (trigVector->GetHeMuUserInfoMap().count(staId) > 0))
401  {
402  // These information are not carried in HE-SIG-A for a HE TB PPDU,
403  // but they are carried in the Trigger frame soliciting the HE TB PPDU
404  m_txVector->SetGuardInterval(trigVector->GetGuardInterval());
405  m_txVector->SetHeMuUserInfo(staId, trigVector->GetHeMuUserInfo(staId));
406  }
407  else
408  {
409  // Set dummy user info, PPDU will be dropped later after decoding PHY headers.
410  m_txVector->SetHeMuUserInfo(
411  staId,
412  {{HeRu::GetRuType(m_txVector->GetChannelWidth()), 1, true}, 0, 1});
413  }
414 }
415 
416 bool
417 HePpdu::IsAllocated(uint16_t staId) const
418 {
419  return (m_muUserInfos.find(staId) != m_muUserInfos.cend());
420 }
421 
422 bool
423 HePpdu::IsStaInContentChannel(uint16_t staId, std::size_t channelId) const
424 {
425  NS_ASSERT_MSG(channelId < m_contentChannelAlloc.size(),
426  "Invalid content channel ID " << channelId);
427  const auto& channelAlloc = m_contentChannelAlloc.at(channelId);
428  return (std::find(channelAlloc.cbegin(), channelAlloc.cend(), staId) != channelAlloc.cend());
429 }
430 
431 std::string
433 {
434  std::ostringstream ss;
435  if (IsMu())
436  {
437  ss << m_psdus;
438  ss << ", " << m_txPsdFlag;
439  }
440  else
441  {
442  ss << "PSDU=" << m_psdus.at(SU_STA_ID) << " ";
443  }
444  return ss.str();
445 }
446 
448  : m_format(1),
449  m_bssColor(0),
450  m_ul_dl(0),
451  m_mcs(0),
452  m_spatialReuse(0),
453  m_bandwidth(0),
454  m_gi_ltf_size(0),
455  m_nsts(0),
456  m_mu(false)
457 {
458 }
459 
460 TypeId
462 {
463  static TypeId tid = TypeId("ns3::HeSigHeader")
464  .SetParent<Header>()
465  .SetGroupName("Wifi")
466  .AddConstructor<HeSigHeader>();
467  return tid;
468 }
469 
470 TypeId
472 {
473  return GetTypeId();
474 }
475 
476 void
477 HePpdu::HeSigHeader::Print(std::ostream& os) const
478 {
479  os << "MCS=" << +m_mcs << " CHANNEL_WIDTH=" << GetChannelWidth() << " GI=" << GetGuardInterval()
480  << " NSTS=" << +m_nsts << " BSSColor=" << +m_bssColor << " MU=" << +m_mu;
481 }
482 
483 uint32_t
485 {
486  uint32_t size = 0;
487  size += 4; // HE-SIG-A1
488  size += 4; // HE-SIG-A2
489  if (m_mu)
490  {
491  size += 1; // HE-SIG-B
492  }
493  return size;
494 }
495 
496 void
498 {
499  m_mu = mu;
500 }
501 
502 void
504 {
505  // NS_ASSERT (mcs <= 11); // TODO: reactivate once EHT PHY headers are implemented
506  m_mcs = mcs;
507 }
508 
509 uint8_t
511 {
512  return m_mcs;
513 }
514 
515 void
517 {
518  NS_ASSERT(bssColor < 64);
519  m_bssColor = bssColor;
520 }
521 
522 uint8_t
524 {
525  return m_bssColor;
526 }
527 
528 void
530 {
531  if (channelWidth == 160)
532  {
533  m_bandwidth = 3;
534  }
535  else if (channelWidth == 80)
536  {
537  m_bandwidth = 2;
538  }
539  else if (channelWidth == 40)
540  {
541  m_bandwidth = 1;
542  }
543  else
544  {
545  m_bandwidth = 0;
546  }
547 }
548 
549 uint16_t
551 {
552  if (m_bandwidth == 3)
553  {
554  return 160;
555  }
556  else if (m_bandwidth == 2)
557  {
558  return 80;
559  }
560  else if (m_bandwidth == 1)
561  {
562  return 40;
563  }
564  else
565  {
566  return 20;
567  }
568 }
569 
570 void
572 {
573  if (gi == 800 && ltf == 1)
574  {
575  m_gi_ltf_size = 0;
576  }
577  else if (gi == 800 && ltf == 2)
578  {
579  m_gi_ltf_size = 1;
580  }
581  else if (gi == 1600 && ltf == 2)
582  {
583  m_gi_ltf_size = 2;
584  }
585  else
586  {
587  m_gi_ltf_size = 3;
588  }
589 }
590 
591 uint16_t
593 {
594  if (m_gi_ltf_size == 3)
595  {
596  // we currently do not consider DCM nor STBC fields
597  return 3200;
598  }
599  else if (m_gi_ltf_size == 2)
600  {
601  return 1600;
602  }
603  else
604  {
605  return 800;
606  }
607 }
608 
609 void
611 {
612  NS_ASSERT(nStreams <= 8);
613  m_nsts = (nStreams - 1);
614 }
615 
616 uint8_t
618 {
619  return (m_nsts + 1);
620 }
621 
622 void
624 {
625  // HE-SIG-A1
626  uint8_t byte = m_format & 0x01;
627  byte |= ((m_ul_dl & 0x01) << 2);
628  byte |= ((m_mcs & 0x0f) << 3);
629  start.WriteU8(byte);
630  uint16_t bytes = (m_bssColor & 0x3f);
631  bytes |= (0x01 << 6); // Reserved set to 1
632  bytes |= ((m_spatialReuse & 0x0f) << 7);
633  bytes |= ((m_bandwidth & 0x03) << 11);
634  bytes |= ((m_gi_ltf_size & 0x03) << 13);
635  bytes |= ((m_nsts & 0x01) << 15);
636  start.WriteU16(bytes);
637  start.WriteU8((m_nsts >> 1) & 0x03);
638 
639  // HE-SIG-A2
640  uint32_t sigA2 = 0;
641  sigA2 |= (0x01 << 14); // Set Reserved bit #14 to 1
642  start.WriteU32(sigA2);
643 
644  if (m_mu)
645  {
646  // HE-SIG-B
647  start.WriteU8(0);
648  }
649 }
650 
651 uint32_t
653 {
655 
656  // HE-SIG-A1
657  uint8_t byte = i.ReadU8();
658  m_format = (byte & 0x01);
659  m_ul_dl = ((byte >> 2) & 0x01);
660  m_mcs = ((byte >> 3) & 0x0f);
661  uint16_t bytes = i.ReadU16();
662  m_bssColor = (bytes & 0x3f);
663  m_spatialReuse = ((bytes >> 7) & 0x0f);
664  m_bandwidth = ((bytes >> 11) & 0x03);
665  m_gi_ltf_size = ((bytes >> 13) & 0x03);
666  m_nsts = ((bytes >> 15) & 0x01);
667  byte = i.ReadU8();
668  m_nsts |= (byte & 0x03) << 1;
669 
670  // HE-SIG-A2
671  i.ReadU32();
672 
673  if (m_mu)
674  {
675  // HE-SIG-B
676  i.ReadU8();
677  }
678 
679  return i.GetDistanceFrom(start);
680 }
681 
682 } // 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
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition: he-phy.cc:1559
HE-SIG PHY header (HE-SIG-A1/A2/B)
Definition: he-ppdu.h:51
static TypeId GetTypeId()
Get the type ID.
Definition: he-ppdu.cc:461
void SetChannelWidth(uint16_t channelWidth)
Fill the channel width field of HE-SIG-A1 (in MHz).
Definition: he-ppdu.cc:529
uint16_t GetGuardInterval() const
Return the guard interval (in nanoseconds).
Definition: he-ppdu.cc:592
void SetBssColor(uint8_t bssColor)
Fill the BSS Color field of HE-SIG-A1.
Definition: he-ppdu.cc:516
uint8_t GetBssColor() const
Return the BSS Color field in the HE-SIG-A1.
Definition: he-ppdu.cc:523
uint8_t GetMcs() const
Return the MCS field of HE-SIG-A1.
Definition: he-ppdu.cc:510
uint32_t GetSerializedSize() const override
Definition: he-ppdu.cc:484
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: he-ppdu.cc:471
void SetMuFlag(bool mu)
Set the Multi-User (MU) flag.
Definition: he-ppdu.cc:497
uint16_t GetChannelWidth() const
Return the channel width (in MHz).
Definition: he-ppdu.cc:550
void Print(std::ostream &os) const override
Definition: he-ppdu.cc:477
void Serialize(Buffer::Iterator start) const override
Definition: he-ppdu.cc:623
void SetGuardIntervalAndLtfSize(uint16_t gi, uint8_t ltf)
Fill the GI + LTF size field of HE-SIG-A1.
Definition: he-ppdu.cc:571
void SetMcs(uint8_t mcs)
Fill the MCS field of HE-SIG-A1.
Definition: he-ppdu.cc:503
uint8_t GetNStreams() const
Return the number of streams.
Definition: he-ppdu.cc:617
void SetNStreams(uint8_t nStreams)
Fill the number of streams field of HE-SIG-A1.
Definition: he-ppdu.cc:610
void SetTxPsdFlag(TxPsdFlag flag) const
Definition: he-ppdu.cc:374
WifiTxVector DoGetTxVector() const override
Get the TXVECTOR used to send the PPDU.
Definition: he-ppdu.cc:165
void UpdateTxVectorForUlMu(const std::optional< WifiTxVector > &trigVector) const
Update the TXVECTOR for HE TB PPDUs, since the information to decode HE TB PPDUs is not available fro...
Definition: he-ppdu.cc:381
Ptr< WifiPpdu > Copy() const override
Copy this instance.
Definition: he-ppdu.cc:261
virtual void SetTxVectorFromPhyHeaders(WifiTxVector &txVector, const LSigHeader &lSig, const HeSigHeader &heSig) const
Fill in the TXVECTOR from PHY headers.
Definition: he-ppdu.cc:194
TxPsdFlag
The transmit power spectral density flag, namely used to correctly build PSDs for pre-HE and HE porti...
Definition: he-ppdu.h:156
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition: he-ppdu.h:158
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
Definition: he-ppdu.h:157
virtual bool IsDlMu() const
Return true if the PPDU is a DL MU PPDU.
Definition: he-ppdu.cc:287
Time GetTxDuration() const override
Get the total transmission duration of the PPDU.
Definition: he-ppdu.cc:226
virtual bool IsUlMu() const
Return true if the PPDU is an UL MU PPDU.
Definition: he-ppdu.cc:293
ContentChannelAllocation m_contentChannelAlloc
HE SIG-B Content Channel allocation (to be removed once HE-SIG-B headers are implemented)
Definition: he-ppdu.h:271
WifiTxVector::HeMuUserInfoMap m_muUserInfos
HE MU specific per-user information (to be removed once HE-SIG-B headers are implemented)
Definition: he-ppdu.h:268
virtual void SetPhyHeaders(const WifiTxVector &txVector, Time ppduDuration)
Fill in the PHY headers.
Definition: he-ppdu.cc:106
bool IsAllocated(uint16_t staId) const
Check if STA ID is allocated.
Definition: he-ppdu.cc:417
std::string PrintPayload() const override
Print the payload of the PPDU.
Definition: he-ppdu.cc:432
uint16_t GetStaId() const override
Get the ID of the STA that transmitted the PPDU for UL MU, SU_STA_ID otherwise.
Definition: he-ppdu.cc:342
WifiPpduType GetType() const override
Return the PPDU type (.
Definition: he-ppdu.cc:267
TxPsdFlag GetTxPsdFlag() const
Definition: he-ppdu.cc:368
HePpdu(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint16_t txCenterFreq, Time ppduDuration, WifiPhyBand band, uint64_t uid)
Create an SU HE PPDU, storing a PSDU.
Definition: he-ppdu.cc:86
virtual bool IsMu() const
Return true if the PPDU is a MU PPDU.
Definition: he-ppdu.cc:281
RuAllocation m_ruAllocation
RU_ALLOCATION in SIG-B common field (to be removed once HE-SIG-B headers are implemented)
Definition: he-ppdu.h:273
virtual void SetLSigHeader(LSigHeader &lSig, Time ppduDuration) const
Fill in the L-SIG header.
Definition: he-ppdu.cc:126
bool IsStaInContentChannel(uint16_t staId, size_t channelId) const
Check if STA ID is in HE SIG-B Content Channel ID.
Definition: he-ppdu.cc:423
TxPsdFlag m_txPsdFlag
the transmit power spectral density flag
Definition: he-ppdu.h:266
void SetHeSigHeader(HeSigHeader &heSig, const WifiTxVector &txVector) const
Fill in the HE-SIG header.
Definition: he-ppdu.cc:144
uint16_t GetTransmissionChannelWidth() const override
Get the channel width over which the PPDU will effectively be transmitted.
Definition: he-ppdu.cc:349
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:744
static RuType GetRuType(uint16_t bandwidth)
Get the RU corresponding to the approximate bandwidth.
Definition: he-ru.cc:769
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
WifiPhyBand m_band
the WifiPhyBand used to transmit that PPDU
Definition: ofdm-ppdu.h:125
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
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
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
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1473
std::optional< WifiTxVector > m_txVector
the TXVECTOR at TX PHY or the reconstructed TXVECTOR at RX PHY (or std::nullopt if TXVECTOR has not b...
Definition: wifi-ppdu.h:207
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
WifiModulationClass GetModulation() const
Get the modulation used for the PPDU.
Definition: wifi-ppdu.cc:136
virtual uint16_t GetTransmissionChannelWidth() const
Get the channel width over which the PPDU will effectively be transmitted.
Definition: wifi-ppdu.cc:142
WifiConstPsduMap m_psdus
the PSDUs contained in this PPDU
Definition: wifi-ppdu.h:203
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...
const RuAllocation & GetRuAllocation() const
Get RU Allocation of SIG-B.
uint16_t GetGuardInterval() const
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
uint8_t GetBssColor() const
Get the BSS color.
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 SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
bool IsDlMu() const
void SetRuAllocation(const RuAllocation &ruAlloc)
Set RU Allocation of SIG-B common field.
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
ContentChannelAllocation GetContentChannelAllocation() const
Get the HE SIG-B content channel STA ID allocation IEEE 802.11ax-2021 27.3.11.8.2 HE-SIG-B content ch...
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.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
bool IsUlMu() const
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
void SetBssColor(uint8_t color)
Set the BSS color.
uint16_t GetChannelWidth() const
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
WifiMode GetSigBMode() const
Get MCS used for SIG-B.
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_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:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#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 ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
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_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_PPDU_TYPE_UL_MU
@ WIFI_PPDU_TYPE_SU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Declaration of ns3::HePhy class and ns3::HeSigAParameters struct.
Declaration of ns3::HePpdu class.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
bool IsDlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a downlink multi-user transmission.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
bool IsUlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a uplink multi-user transmission.
Definition: second.py:1
#define SU_STA_ID
Definition: wifi-mode.h:34