A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
he-phy.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 * Authors: Rediet <getachew.redieteab@orange.com>
18 * Sébastien Deronne <sebastien.deronne@gmail.com> (for logic ported from wifi-phy and
19 * spectrum-wifi-phy)
20 */
21
22#include "he-phy.h"
23
24#include "he-configuration.h"
25#include "obss-pd-algorithm.h"
26
27#include "ns3/ap-wifi-mac.h"
28#include "ns3/assert.h"
29#include "ns3/interference-helper.h"
30#include "ns3/log.h"
31#include "ns3/simulator.h"
32#include "ns3/sta-wifi-mac.h"
33#include "ns3/vht-configuration.h"
34#include "ns3/wifi-net-device.h"
35#include "ns3/wifi-phy.h"
36#include "ns3/wifi-psdu.h"
37#include "ns3/wifi-utils.h"
38
39#include <algorithm>
40
41#undef NS_LOG_APPEND_CONTEXT
42#define NS_LOG_APPEND_CONTEXT WIFI_PHY_NS_LOG_APPEND_CONTEXT(m_wifiPhy)
43
44namespace ns3
45{
46
48
49/*******************************************************
50 * HE PHY (P802.11ax/D4.0, clause 27)
51 *******************************************************/
52
53// clang-format off
54
55const PhyEntity::PpduFormats HePhy::m_hePpduFormats { // Ignoring PE (Packet Extension)
57 WIFI_PPDU_FIELD_NON_HT_HEADER, // L-SIG + RL-SIG
58 WIFI_PPDU_FIELD_SIG_A, // HE-SIG-A
59 WIFI_PPDU_FIELD_TRAINING, // HE-STF + HE-LTFs
62 WIFI_PPDU_FIELD_NON_HT_HEADER, // L-SIG + RL-SIG
63 WIFI_PPDU_FIELD_SIG_A, // HE-SIG-A
64 WIFI_PPDU_FIELD_SIG_B, // HE-SIG-B
65 WIFI_PPDU_FIELD_TRAINING, // HE-STF + HE-LTFs
68 WIFI_PPDU_FIELD_NON_HT_HEADER, // L-SIG + RL-SIG
69 WIFI_PPDU_FIELD_SIG_A, // HE-SIG-A
70 WIFI_PPDU_FIELD_TRAINING, // HE-STF + HE-LTFs
73 WIFI_PPDU_FIELD_NON_HT_HEADER, // L-SIG + RL-SIG
74 WIFI_PPDU_FIELD_SIG_A, // HE-SIG-A
75 WIFI_PPDU_FIELD_TRAINING, // HE-STF + HE-LTFs
77};
78
79// clang-format on
80
81HePhy::HePhy(bool buildModeList /* = true */)
82 : VhtPhy(false), // don't add VHT modes to list
83 m_trigVector(std::nullopt),
84 m_trigVectorExpirationTime(std::nullopt),
85 m_currentTxVector(std::nullopt),
86 m_rxHeTbPpdus(0),
87 m_lastPer20MHzDurations()
88{
89 NS_LOG_FUNCTION(this << buildModeList);
93 m_currentMuPpduUid = UINT64_MAX;
94 m_previouslyTxPpduUid = UINT64_MAX;
95 if (buildModeList)
96 {
98 }
99}
100
102{
103 NS_LOG_FUNCTION(this);
104}
105
106void
108{
109 NS_LOG_FUNCTION(this);
110 NS_ASSERT(m_modeList.empty());
112 for (uint8_t index = 0; index <= m_maxSupportedMcsIndexPerSs; ++index)
113 {
114 NS_LOG_LOGIC("Add HeMcs" << +index << " to list");
115 m_modeList.emplace_back(CreateHeMcs(index));
116 }
117}
118
120HePhy::GetSigMode(WifiPpduField field, const WifiTxVector& txVector) const
121{
122 switch (field)
123 {
124 case WIFI_PPDU_FIELD_TRAINING: // consider SIG-A (SIG-B) mode for training for the time being
125 // for SU/ER-SU/TB (MU) (useful for InterferenceHelper)
126 if (txVector.IsDlMu())
127 {
129 // Training comes after SIG-B
130 return GetSigBMode(txVector);
131 }
132 else
133 {
134 // Training comes after SIG-A
135 return GetSigAMode();
136 }
137 default:
138 return VhtPhy::GetSigMode(field, txVector);
139 }
140}
141
144{
145 return GetVhtMcs0(); // same number of data tones as VHT for 20 MHz (i.e. 52)
146}
147
149HePhy::GetSigBMode(const WifiTxVector& txVector) const
150{
151 NS_ABORT_MSG_IF(!IsDlMu(txVector.GetPreambleType()), "SIG-B only available for DL MU");
152 /**
153 * Get smallest HE MCS index among station's allocations and use the
154 * VHT version of the index. This enables to have 800 ns GI, 52 data
155 * tones, and 312.5 kHz spacing while ensuring that MCS will be decoded
156 * by all stations.
157 */
158 uint8_t smallestMcs = 5; // maximum MCS for HE-SIG-B
159 for (auto& info : txVector.GetHeMuUserInfoMap())
160 {
161 smallestMcs = std::min(smallestMcs, info.second.mcs);
162 }
163 switch (smallestMcs)
164 {
165 case 0:
166 return GetVhtMcs0();
167 case 1:
168 return GetVhtMcs1();
169 case 2:
170 return GetVhtMcs2();
171 case 3:
172 return GetVhtMcs3();
173 case 4:
174 return GetVhtMcs4();
175 case 5:
176 default:
177 return GetVhtMcs5();
178 }
179}
180
183{
184 return m_hePpduFormats;
185}
186
187Time
189{
190 return MicroSeconds(8); // L-SIG + RL-SIG
191}
192
193Time
195 uint8_t nDataLtf,
196 uint8_t nExtensionLtf /* = 0 */) const
197{
198 Time ltfDuration = MicroSeconds(8); // TODO extract from TxVector when available
199 Time stfDuration;
200 if (txVector.IsUlMu())
201 {
203 stfDuration = MicroSeconds(8);
204 }
205 else
206 {
207 stfDuration = MicroSeconds(4);
208 }
209 NS_ABORT_MSG_IF(nDataLtf > 8, "Unsupported number of LTFs " << +nDataLtf << " for HE");
210 NS_ABORT_MSG_IF(nExtensionLtf > 0, "No extension LTFs expected for HE");
211 return stfDuration + ltfDuration * nDataLtf; // HE-STF + HE-LTFs
212}
213
214Time
216{
217 return (preamble == WIFI_PREAMBLE_HE_ER_SU)
218 ? MicroSeconds(16)
219 : MicroSeconds(8); // HE-SIG-A (first and second symbol)
220}
221
223HePhy::GetSigBSize(const WifiTxVector& txVector) const
224{
225 if (ns3::IsDlMu(txVector.GetPreambleType()))
226 {
229 txVector.GetChannelWidth(),
230 txVector.GetRuAllocation(
232 txVector.IsSigBCompression(),
233 txVector.IsSigBCompression() ? txVector.GetHeMuUserInfoMap().size() : 0);
234 }
235 return 0;
236}
237
238Time
240{
241 if (auto sigBSize = GetSigBSize(txVector); sigBSize > 0)
242 {
243 auto symbolDuration = MicroSeconds(4);
244 // Number of data bits per symbol
245 auto ndbps =
246 GetSigBMode(txVector).GetDataRate(20, 800, 1) * symbolDuration.GetNanoSeconds() / 1e9;
247 auto numSymbols = ceil((sigBSize) / ndbps);
248
249 return FemtoSeconds(static_cast<uint64_t>(numSymbols * symbolDuration.GetFemtoSeconds()));
250 }
251 else
252 {
253 // no SIG-B
254 return MicroSeconds(0);
255 }
256}
257
258Time
259HePhy::GetValidPpduDuration(Time ppduDuration, const WifiTxVector& txVector, WifiPhyBand band)
260{
261 Time tSymbol = NanoSeconds(12800 + txVector.GetGuardInterval());
262 Time preambleDuration = WifiPhy::CalculatePhyPreambleAndHeaderDuration(txVector);
263 uint8_t sigExtension = (band == WIFI_PHY_BAND_2_4GHZ ? 6 : 0);
264 uint32_t nSymbols =
265 floor(static_cast<double>((ppduDuration - preambleDuration).GetNanoSeconds() -
266 (sigExtension * 1000)) /
267 tSymbol.GetNanoSeconds());
268 return preambleDuration + (nSymbols * tSymbol) + MicroSeconds(sigExtension);
269}
270
271std::pair<uint16_t, Time>
273 const WifiTxVector& txVector,
274 WifiPhyBand band)
275{
276 NS_ABORT_IF(!txVector.IsUlMu() || (txVector.GetModulationClass() < WIFI_MOD_CLASS_HE));
277 // update ppduDuration so that it is a valid PPDU duration
278 ppduDuration = GetValidPpduDuration(ppduDuration, txVector, band);
279 uint8_t sigExtension = (band == WIFI_PHY_BAND_2_4GHZ ? 6 : 0);
280 uint8_t m = 2; // HE TB PPDU so m is set to 2
281 uint16_t length = ((ceil((static_cast<double>(ppduDuration.GetNanoSeconds() - (20 * 1000) -
282 (sigExtension * 1000)) /
283 1000) /
284 4.0) *
285 3) -
286 3 - m);
287 return {length, ppduDuration};
288}
289
290Time
292 const WifiTxVector& txVector,
293 WifiPhyBand band)
294{
295 NS_ABORT_IF(!txVector.IsUlMu() || (txVector.GetModulationClass() < WIFI_MOD_CLASS_HE));
296 uint8_t sigExtension = (band == WIFI_PHY_BAND_2_4GHZ ? 6 : 0);
297 uint8_t m = 2; // HE TB PPDU so m is set to 2
298 // Equation 27-11 of IEEE P802.11ax/D4.0
299 Time calculatedDuration =
300 MicroSeconds(((ceil(static_cast<double>(length + 3 + m) / 3)) * 4) + 20 + sigExtension);
301 return GetValidPpduDuration(calculatedDuration, txVector, band);
302}
303
304Time
306{
307 Time duration = GetDuration(WIFI_PPDU_FIELD_PREAMBLE, txVector) +
310 return duration;
311}
312
313Time
315{
316 Time duration = GetDuration(WIFI_PPDU_FIELD_PREAMBLE, txVector) +
320 return duration;
321}
322
323uint8_t
324HePhy::GetNumberBccEncoders(const WifiTxVector& /* txVector */) const
325{
326 return 1; // only 1 BCC encoder for HE since higher rates are obtained using LDPC
327}
328
329Time
331{
332 uint16_t gi = txVector.GetGuardInterval();
333 NS_ASSERT(gi == 800 || gi == 1600 || gi == 3200);
334 return GetSymbolDuration(NanoSeconds(gi));
335}
336
337void
338HePhy::SetTrigVector(const WifiTxVector& trigVector, Time validity)
339{
340 NS_LOG_FUNCTION(this << trigVector << validity);
341 NS_ASSERT_MSG(trigVector.GetGuardInterval() > 800,
342 "Invalid guard interval " << trigVector.GetGuardInterval());
343 if (auto mac = m_wifiPhy->GetDevice()->GetMac(); mac && mac->GetTypeOfStation() != AP)
344 {
345 return;
346 }
347 m_trigVector = trigVector;
350}
351
353HePhy::BuildPpdu(const WifiConstPsduMap& psdus, const WifiTxVector& txVector, Time ppduDuration)
354{
355 NS_LOG_FUNCTION(this << psdus << txVector << ppduDuration);
356 return Create<HePpdu>(psdus,
357 txVector,
359 ppduDuration,
360 ObtainNextUid(txVector),
362}
363
364void
366 RxPowerWattPerChannelBand& rxPowersW,
367 Time rxDuration)
368{
369 NS_LOG_FUNCTION(this << ppdu << rxDuration);
370 const auto& txVector = ppdu->GetTxVector();
371 auto hePpdu = DynamicCast<const HePpdu>(ppdu);
372 NS_ASSERT(hePpdu);
373 const auto psdFlag = hePpdu->GetTxPsdFlag();
374 if (psdFlag == HePpdu::PSD_HE_PORTION)
375 {
376 NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
377 if (m_currentMuPpduUid == ppdu->GetUid() && GetCurrentEvent())
378 {
379 // AP or STA has already received non-HE portion, switch to HE portion, and schedule
380 // reception of payload (will be canceled for STAs by StartPayload)
381 bool hePortionStarted = !m_beginMuPayloadRxEvents.empty();
382 NS_LOG_INFO("Switch to HE portion (already started? "
383 << (hePortionStarted ? "Y" : "N") << ") "
384 << "and schedule payload reception in "
386 auto event = CreateInterferenceEvent(ppdu, rxDuration, rxPowersW, !hePortionStarted);
387 uint16_t staId = GetStaId(ppdu);
388 NS_ASSERT(!m_beginMuPayloadRxEvents.contains(staId));
392 this,
393 event);
394 }
395 else
396 {
397 // PHY receives the HE portion while having dropped the preamble
398 NS_LOG_INFO("Consider HE portion of the PPDU as interference since device dropped the "
399 "preamble");
400 CreateInterferenceEvent(ppdu, rxDuration, rxPowersW);
401 // the HE portion of the PPDU will be noise _after_ the completion of the current event
402 ErasePreambleEvent(ppdu, rxDuration);
403 }
404 }
405 else
406 {
408 ppdu,
409 rxPowersW,
410 ppdu->GetTxDuration()); // The actual duration of the PPDU should be used
411 }
412}
413
414void
416{
417 NS_LOG_FUNCTION(this);
418 for (auto& beginMuPayloadRxEvent : m_beginMuPayloadRxEvents)
419 {
420 beginMuPayloadRxEvent.second.Cancel();
421 }
424}
425
426void
428{
429 NS_LOG_FUNCTION(this << reason);
430 if (reason != OBSS_PD_CCA_RESET)
431 {
432 for (auto& endMpduEvent : m_endOfMpduEvents)
433 {
434 endMpduEvent.Cancel();
435 }
436 m_endOfMpduEvents.clear();
437 }
438 else
439 {
441 }
442}
443
444void
446{
447 NS_LOG_FUNCTION(this << *event);
448 if (event->GetPpdu()->GetType() != WIFI_PPDU_TYPE_UL_MU)
449 {
450 NS_ASSERT(event->GetEndTime() == Simulator::Now());
451 }
452 for (auto& beginMuPayloadRxEvent : m_beginMuPayloadRxEvents)
453 {
454 beginMuPayloadRxEvent.second.Cancel();
455 }
457}
458
461{
462 Ptr<Event> event;
463 // We store all incoming preamble events, and a decision is made at the end of the preamble
464 // detection window. If a preamble is received after the preamble detection window, it is stored
465 // anyway because this is needed for HE TB PPDUs in order to properly update the received power
466 // in InterferenceHelper. The map is cleaned anyway at the end of the current reception.
467 const auto& currentPreambleEvents = GetCurrentPreambleEvents();
468 const auto it = currentPreambleEvents.find({ppdu->GetUid(), ppdu->GetPreamble()});
469 if (const auto isResponseToTrigger = (m_previouslyTxPpduUid == ppdu->GetUid());
470 ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU || isResponseToTrigger)
471 {
472 const auto& txVector = ppdu->GetTxVector();
473 const auto rxDuration =
474 (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
476 txVector) // the HE portion of the transmission will be added later on
477 : ppdu->GetTxDuration();
478 if (it != currentPreambleEvents.cend())
479 {
480 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
481 {
482 NS_LOG_DEBUG("Received another HE TB PPDU for UID "
483 << ppdu->GetUid() << " from STA-ID " << ppdu->GetStaId()
484 << " and BSS color " << +txVector.GetBssColor());
485 }
486 else
487 {
488 NS_LOG_DEBUG("Received another response to a trigger frame " << ppdu->GetUid());
489 }
490 event = it->second;
491 HandleRxPpduWithSameContent(event, ppdu, rxPowersW);
492 return nullptr;
493 }
494 else
495 {
496 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
497 {
498 NS_LOG_DEBUG("Received a new HE TB PPDU for UID "
499 << ppdu->GetUid() << " from STA-ID " << ppdu->GetStaId()
500 << " and BSS color " << +txVector.GetBssColor());
501 }
502 else
503 {
504 NS_LOG_DEBUG("Received response to a trigger frame for UID " << ppdu->GetUid());
505 }
506 event = CreateInterferenceEvent(ppdu, rxDuration, rxPowersW);
507 AddPreambleEvent(event);
508 }
509 }
510 else if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
511 {
512 const auto& txVector = ppdu->GetTxVector();
514 txVector); // the HE portion of the transmission will be added later on
515 event = CreateInterferenceEvent(ppdu, rxDuration, rxPowersW);
516 AddPreambleEvent(event);
517 }
518 else
519 {
520 event = VhtPhy::DoGetEvent(ppdu, rxPowersW);
521 }
522 return event;
523}
524
525void
529{
530 VhtPhy::HandleRxPpduWithSameContent(event, ppdu, rxPower);
531
532 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU && GetCurrentEvent() &&
533 (GetCurrentEvent()->GetPpdu()->GetUid() != ppdu->GetUid()))
534 {
535 NS_LOG_DEBUG("Drop packet because already receiving another HE TB PPDU");
537 }
538 else if (const auto isResponseToTrigger = (m_previouslyTxPpduUid == ppdu->GetUid());
539 isResponseToTrigger && GetCurrentEvent() &&
540 (GetCurrentEvent()->GetPpdu()->GetUid() != ppdu->GetUid()))
541 {
542 NS_LOG_DEBUG("Drop packet because already receiving another response to a trigger frame");
544 }
545}
546
549{
550 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU || ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
551 {
552 auto hePpdu = DynamicCast<const HePpdu>(ppdu);
553 NS_ASSERT(hePpdu);
554 return hePpdu->GetPsdu(GetBssColor(), GetStaId(ppdu));
555 }
557}
558
559uint8_t
561{
562 uint8_t bssColor = 0;
563 if (m_wifiPhy->GetDevice())
564 {
566 if (heConfiguration)
567 {
568 bssColor = heConfiguration->GetBssColor();
569 }
570 }
571 return bssColor;
572}
573
574uint16_t
576{
577 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
578 {
579 return ppdu->GetStaId();
580 }
581 else if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
582 {
583 auto mac = DynamicCast<StaWifiMac>(m_wifiPhy->GetDevice()->GetMac());
584 if (mac && mac->IsAssociated())
585 {
586 return mac->GetAssociationId();
587 }
588 }
589 return VhtPhy::GetStaId(ppdu);
590}
591
594{
595 NS_LOG_FUNCTION(this << *event << status << field);
596 NS_ASSERT(event->GetPpdu()->GetTxVector().GetPreambleType() >= WIFI_PREAMBLE_HE_SU);
597 switch (field)
598 {
600 return ProcessSigA(event, status);
602 return ProcessSigB(event, status);
603 default:
604 NS_ASSERT_MSG(false, "Invalid PPDU field");
605 }
606 return status;
607}
608
611{
612 NS_LOG_FUNCTION(this << *event << status);
613 // Notify end of SIG-A (in all cases)
614 const auto& txVector = event->GetPpdu()->GetTxVector();
615 HeSigAParameters params;
616 params.rssiW = GetRxPowerWForPpdu(event);
617 params.bssColor = txVector.GetBssColor();
618 NotifyEndOfHeSigA(params); // if OBSS_PD CCA_RESET, set power restriction first and wait till
619 // field is processed before switching to IDLE
620
621 if (status.isSuccess)
622 {
623 // Check if PPDU is filtered based on the BSS color
624 uint8_t myBssColor = GetBssColor();
625 uint8_t rxBssColor = txVector.GetBssColor();
626 if (myBssColor != 0 && rxBssColor != 0 && myBssColor != rxBssColor)
627 {
628 NS_LOG_DEBUG("The BSS color of this PPDU ("
629 << +rxBssColor << ") does not match the device's (" << +myBssColor
630 << "). The PPDU is filtered.");
631 return PhyFieldRxStatus(false, FILTERED, DROP);
632 }
633
634 // When SIG-A is decoded, we know the type of frame being received. If we stored a
635 // valid TRIGVECTOR and we are not receiving a TB PPDU, we drop the frame.
636 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
637 if (m_trigVectorExpirationTime.has_value() &&
639 (ppdu->GetType() != WIFI_PPDU_TYPE_UL_MU))
640 {
641 NS_LOG_DEBUG("Expected an HE TB PPDU, receiving a " << txVector.GetPreambleType());
642 return PhyFieldRxStatus(false, FILTERED, DROP);
643 }
644
645 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
646 {
647 NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
648 // check that the stored TRIGVECTOR is still valid
649 if (!m_trigVectorExpirationTime.has_value() ||
651 {
652 NS_LOG_DEBUG("No valid TRIGVECTOR, the PHY was not expecting a TB PPDU");
653 return PhyFieldRxStatus(false, FILTERED, DROP);
654 }
655 // We expected a TB PPDU and we are receiving a TB PPDU. However, despite
656 // the previous check on BSS Color, we may be receiving a TB PPDU from an
657 // OBSS, as BSS Colors are not guaranteed to be different for all APs in
658 // range (an example is when BSS Color is 0). We can detect this situation
659 // by comparing the TRIGVECTOR with the TXVECTOR of the TB PPDU being received
660 NS_ABORT_IF(!m_trigVector.has_value());
661 if (m_trigVector->GetChannelWidth() != txVector.GetChannelWidth())
662 {
663 NS_LOG_DEBUG("Received channel width different than in TRIGVECTOR");
664 return PhyFieldRxStatus(false, FILTERED, DROP);
665 }
666 if (m_trigVector->GetLength() != txVector.GetLength())
667 {
668 NS_LOG_DEBUG("Received UL Length (" << txVector.GetLength()
669 << ") different than in TRIGVECTOR ("
670 << m_trigVector->GetLength() << ")");
671 return PhyFieldRxStatus(false, FILTERED, DROP);
672 }
673 uint16_t staId = ppdu->GetStaId();
674 if (!m_trigVector->GetHeMuUserInfoMap().contains(staId))
675 {
676 NS_LOG_DEBUG("TB PPDU received from un unexpected STA ID");
677 return PhyFieldRxStatus(false, FILTERED, DROP);
678 }
679
680 NS_ASSERT(txVector.GetGuardInterval() == m_trigVector->GetGuardInterval());
681 NS_ASSERT(txVector.GetMode(staId) == m_trigVector->GetMode(staId));
682 NS_ASSERT(txVector.GetNss(staId) == m_trigVector->GetNss(staId));
683 NS_ASSERT(txVector.GetHeMuUserInfo(staId) == m_trigVector->GetHeMuUserInfo(staId));
684
686 ppdu->GetUid(); // to be able to correctly schedule start of MU payload
687 }
688
689 if (ppdu->GetType() != WIFI_PPDU_TYPE_DL_MU &&
690 !GetAddressedPsduInPpdu(ppdu)) // Final decision on STA-ID correspondence of DL MU is
691 // delayed to end of SIG-B
692 {
693 NS_ASSERT(ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU);
695 "No PSDU addressed to that PHY in the received MU PPDU. The PPDU is filtered.");
696 return PhyFieldRxStatus(false, FILTERED, DROP);
697 }
698 }
699 return status;
700}
701
702void
704{
705 m_obssPdAlgorithm = algorithm;
706}
707
710{
711 return m_obssPdAlgorithm;
712}
713
714void
716{
717 m_endOfHeSigACallback = callback;
718}
719
720void
722{
724 {
725 m_endOfHeSigACallback(params);
726 }
727}
728
731{
732 NS_LOG_FUNCTION(this << *event << status);
733 NS_ASSERT(IsDlMu(event->GetPpdu()->GetTxVector().GetPreambleType()));
734 if (status.isSuccess)
735 {
736 // Check if PPDU is filtered only if the SIG-B content is supported (not explicitly stated
737 // but assumed based on behavior for SIG-A)
738 if (!GetAddressedPsduInPpdu(event->GetPpdu()))
739 {
741 "No PSDU addressed to that PHY in the received MU PPDU. The PPDU is filtered.");
742 return PhyFieldRxStatus(false, FILTERED, DROP);
743 }
744 }
746 event->GetPpdu()->GetUid(); // to be able to correctly schedule start of MU payload
747
748 return status;
749}
750
751bool
753{
754 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
755 {
756 return true; // evaluated in ProcessSigA
757 }
758
759 const auto& txVector = ppdu->GetTxVector();
760 uint16_t staId = GetStaId(ppdu);
761 WifiMode txMode = txVector.GetMode(staId);
762 uint8_t nss = txVector.GetNssMax();
763 if (txVector.IsDlMu())
764 {
765 NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
766 for (auto info : txVector.GetHeMuUserInfoMap())
767 {
768 if (info.first == staId)
769 {
770 nss = info.second.nss; // no need to look at other PSDUs
771 break;
772 }
773 }
774 }
775
777 {
778 NS_LOG_DEBUG("Packet reception could not be started because not enough RX antennas");
779 return false;
780 }
781 if (!IsModeSupported(txMode))
782 {
783 NS_LOG_DEBUG("Drop packet because it was sent using an unsupported mode ("
784 << txVector.GetMode() << ")");
785 return false;
786 }
787 return true;
788}
789
790Time
792{
793 NS_LOG_FUNCTION(this << *event);
794 const auto ppdu = event->GetPpdu();
795 const auto& txVector = ppdu->GetTxVector();
796
797 if (!txVector.IsMu())
798 {
799 return VhtPhy::DoStartReceivePayload(event);
800 }
801
802 NS_ASSERT(txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE);
803
804 if (txVector.IsDlMu())
805 {
806 Time payloadDuration =
807 ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(txVector);
808 NotifyPayloadBegin(txVector, payloadDuration);
809 return payloadDuration;
810 }
811
812 // TX duration is determined by the Length field of TXVECTOR
813 Time payloadDuration = ConvertLSigLengthToHeTbPpduDuration(txVector.GetLength(),
814 txVector,
817 // This method is called when we start receiving the first MU payload. To
818 // compute the time to the reception end of the last TB PPDU, we need to add the
819 // offset of the last TB PPDU to the payload duration (same for all TB PPDUs)
820 Time maxOffset{0};
821 for (const auto& beginMuPayloadRxEvent : m_beginMuPayloadRxEvents)
822 {
823 maxOffset = Max(maxOffset, Simulator::GetDelayLeft(beginMuPayloadRxEvent.second));
824 }
825 Time timeToEndRx = payloadDuration + maxOffset;
826
828 {
829 NS_LOG_DEBUG("Ignore HE TB PPDU payload received by STA but keep state in Rx");
830 NotifyPayloadBegin(txVector, timeToEndRx);
831 m_endRxPayloadEvents.push_back(
832 Simulator::Schedule(timeToEndRx, &HePhy::ResetReceive, this, event));
833 // Cancel all scheduled events for MU payload reception
835 m_beginMuPayloadRxEvents.begin()->second.IsRunning());
836 for (auto& beginMuPayloadRxEvent : m_beginMuPayloadRxEvents)
837 {
838 beginMuPayloadRxEvent.second.Cancel();
839 }
841 }
842 else
843 {
844 NS_LOG_DEBUG("Receiving PSDU in HE TB PPDU");
845 uint16_t staId = GetStaId(ppdu);
846 m_signalNoiseMap.insert({{ppdu->GetUid(), staId}, SignalNoiseDbm()});
847 m_statusPerMpduMap.insert({{ppdu->GetUid(), staId}, std::vector<bool>()});
848 // for HE TB PPDUs, ScheduleEndOfMpdus and EndReceive are scheduled by
849 // StartReceiveMuPayload
851 for (auto& beginMuPayloadRxEvent : m_beginMuPayloadRxEvents)
852 {
853 NS_ASSERT(beginMuPayloadRxEvent.second.IsRunning());
854 }
855 }
856
857 return timeToEndRx;
858}
859
860void
862 RxSignalInfo rxSignalInfo,
863 const WifiTxVector& txVector,
864 uint16_t staId,
865 const std::vector<bool>& statusPerMpdu)
866{
867 NS_LOG_FUNCTION(this << *psdu << txVector);
868 if (!IsUlMu(txVector.GetPreambleType()))
869 {
870 m_state->SwitchFromRxEndOk();
871 }
872 else
873 {
875 }
876}
877
878void
880{
881 NS_LOG_FUNCTION(this << *psdu << txVector << snr);
882 if (!txVector.IsUlMu())
883 {
884 m_state->SwitchFromRxEndError();
885 }
886}
887
888void
890{
891 NS_LOG_FUNCTION(this << ppdu);
892 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
893 {
894 for (auto it = m_endRxPayloadEvents.begin(); it != m_endRxPayloadEvents.end();)
895 {
896 if (it->IsExpired())
897 {
898 it = m_endRxPayloadEvents.erase(it);
899 }
900 else
901 {
902 it++;
903 }
904 }
905 if (m_endRxPayloadEvents.empty())
906 {
907 // We've got the last PPDU of the UL-MU transmission.
908 // Indicate a successful reception is terminated if at least one HE TB PPDU
909 // has been successfully received, otherwise indicate a unsuccessful reception is
910 // terminated.
911 if (m_rxHeTbPpdus > 0)
912 {
913 m_state->SwitchFromRxEndOk();
914 }
915 else
916 {
917 m_state->SwitchFromRxEndError();
918 }
919 NotifyInterferenceRxEndAndClear(true); // reset WifiPhy
920 m_rxHeTbPpdus = 0;
921 }
922 }
923 else
924 {
927 }
928 // we are done receiving the payload, we can reset the current MU PPDU UID
929 m_currentMuPpduUid = UINT64_MAX;
930}
931
932void
934{
935 NS_LOG_FUNCTION(this << event);
936 Ptr<const WifiPpdu> ppdu = event->GetPpdu();
937 const RxPowerWattPerChannelBand& rxPowersW = event->GetRxPowerWPerBand();
938 // The total RX power corresponds to the maximum over all the bands.
939 // Only perform this computation if the result needs to be logged.
940 auto it = rxPowersW.end();
941 if (g_log.IsEnabled(ns3::LOG_FUNCTION))
942 {
943 it = std::max_element(rxPowersW.cbegin(),
944 rxPowersW.cend(),
945 [](const auto& p1, const auto& p2) { return p1.second < p2.second; });
946 }
947 NS_LOG_FUNCTION(this << *event << it->second);
950 auto itEvent = m_beginMuPayloadRxEvents.find(GetStaId(ppdu));
951 /**
952 * m_beginMuPayloadRxEvents should still be running only for APs, since canceled in
953 * StartReceivePayload for STAs. This is because SpectrumWifiPhy does not have access to the
954 * device type and thus blindly schedules things, letting the parent WifiPhy class take into
955 * account device type.
956 */
957 NS_ASSERT(itEvent != m_beginMuPayloadRxEvents.end() && itEvent->second.IsExpired());
958 m_beginMuPayloadRxEvents.erase(itEvent);
959
960 Time payloadDuration =
961 ppdu->GetTxDuration() - CalculatePhyPreambleAndHeaderDuration(ppdu->GetTxVector());
963 ScheduleEndOfMpdus(event);
964 m_endRxPayloadEvents.push_back(
965 Simulator::Schedule(payloadDuration, &HePhy::EndReceivePayload, this, event));
966 uint16_t staId = GetStaId(ppdu);
967 m_signalNoiseMap.insert({{ppdu->GetUid(), staId}, SignalNoiseDbm()});
968 m_statusPerMpduMap.insert({{ppdu->GetUid(), staId}, std::vector<bool>()});
969 // Notify the MAC about the start of a new HE TB PPDU, so that it can reschedule the timeout
970 NotifyPayloadBegin(ppdu->GetTxVector(), payloadDuration);
971}
972
973std::pair<uint16_t, WifiSpectrumBandInfo>
974HePhy::GetChannelWidthAndBand(const WifiTxVector& txVector, uint16_t staId) const
975{
976 if (txVector.IsMu())
977 {
978 return {HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType()),
979 GetRuBandForRx(txVector, staId)};
980 }
981 else
982 {
983 return VhtPhy::GetChannelWidthAndBand(txVector, staId);
984 }
985}
986
988HePhy::GetRuBandForTx(const WifiTxVector& txVector, uint16_t staId) const
989{
990 NS_ASSERT(txVector.IsMu());
991 HeRu::RuSpec ru = txVector.GetRu(staId);
992 uint16_t channelWidth = txVector.GetChannelWidth();
993 NS_ASSERT(channelWidth <= m_wifiPhy->GetChannelWidth());
995 channelWidth,
996 ru.GetRuType(),
998 // for a TX spectrum, the guard bandwidth is a function of the transmission channel width
999 // and the spectrum width equals the transmission channel width (hence bandIndex equals 0)
1000 auto indices = ConvertHeRuSubcarriers(channelWidth,
1001 GetGuardBandwidth(channelWidth),
1003 {group.front().first, group.back().second},
1004 0);
1005 auto frequencies = m_wifiPhy->ConvertIndicesToFrequencies(indices);
1006 return {indices, frequencies};
1007}
1008
1010HePhy::GetRuBandForRx(const WifiTxVector& txVector, uint16_t staId) const
1011{
1012 NS_ASSERT(txVector.IsMu());
1013 HeRu::RuSpec ru = txVector.GetRu(staId);
1014 uint16_t channelWidth = txVector.GetChannelWidth();
1015 NS_ASSERT(channelWidth <= m_wifiPhy->GetChannelWidth());
1017 channelWidth,
1018 ru.GetRuType(),
1020 // for an RX spectrum, the guard bandwidth is a function of the operating channel width
1021 // and the spectrum width equals the operating channel width
1022 auto indices = ConvertHeRuSubcarriers(
1023 channelWidth,
1026 {group.front().first, group.back().second},
1028 auto frequencies = m_wifiPhy->ConvertIndicesToFrequencies(indices);
1029 return {indices, frequencies};
1030}
1031
1033HePhy::GetNonOfdmaBand(const WifiTxVector& txVector, uint16_t staId) const
1034{
1035 NS_ASSERT(txVector.IsUlMu() && (txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE));
1036 uint16_t channelWidth = txVector.GetChannelWidth();
1037 NS_ASSERT(channelWidth <= m_wifiPhy->GetChannelWidth());
1038
1039 HeRu::RuSpec ru = txVector.GetRu(staId);
1040 uint16_t nonOfdmaWidth = GetNonOfdmaWidth(ru);
1041
1042 // Find the RU that encompasses the non-OFDMA part of the HE TB PPDU for the STA-ID
1043 HeRu::RuSpec nonOfdmaRu =
1044 HeRu::FindOverlappingRu(channelWidth, ru, HeRu::GetRuType(nonOfdmaWidth));
1045
1047 channelWidth,
1048 nonOfdmaRu.GetRuType(),
1049 nonOfdmaRu.GetPhyIndex(channelWidth,
1051 auto indices = ConvertHeRuSubcarriers(
1052 channelWidth,
1055 {groupPreamble.front().first, groupPreamble.back().second},
1057 auto frequencies = m_wifiPhy->ConvertIndicesToFrequencies(indices);
1058 return {indices, frequencies};
1059}
1060
1061uint16_t
1063{
1064 if (ru.GetRuType() == HeRu::RU_26_TONE && ru.GetIndex() == 19)
1065 {
1066 // the center 26-tone RU in an 80 MHz channel is not fully covered by
1067 // any 20 MHz channel, but only by an 80 MHz channel
1068 return 80;
1069 }
1070 return std::max<uint16_t>(HeRu::GetBandwidth(ru.GetRuType()), 20);
1071}
1072
1073uint64_t
1075{
1076 return m_currentMuPpduUid;
1077}
1078
1079uint16_t
1081{
1082 uint16_t channelWidth = OfdmPhy::GetMeasurementChannelWidth(ppdu);
1083 /**
1084 * The PHY shall not issue a PHY-RXSTART.indication primitive in response to a PPDU that does
1085 * not overlap the primary channel unless the PHY at an AP receives the HE TB PPDU solicited by
1086 * the AP. For the HE TB PPDU solicited by the AP, the PHY shall issue a PHY-RXSTART.indication
1087 * primitive for a PPDU received in the primary or at the secondary 20 MHz channel, the
1088 * secondary 40 MHz channel, or the secondary 80 MHz channel.
1089 */
1090 if (channelWidth >= 40 && ppdu->GetUid() != m_previouslyTxPpduUid)
1091 {
1092 channelWidth = 20;
1093 }
1094 return channelWidth;
1095}
1096
1097double
1099{
1100 if (!ppdu)
1101 {
1102 return VhtPhy::GetCcaThreshold(ppdu, channelType);
1103 }
1104
1105 if (!m_obssPdAlgorithm)
1106 {
1107 return VhtPhy::GetCcaThreshold(ppdu, channelType);
1108 }
1109
1110 if (channelType == WIFI_CHANLIST_PRIMARY)
1111 {
1112 return VhtPhy::GetCcaThreshold(ppdu, channelType);
1113 }
1114
1115 const uint16_t ppduBw = ppdu->GetTxVector().GetChannelWidth();
1116 double obssPdLevel = m_obssPdAlgorithm->GetObssPdLevel();
1117 uint16_t bw = ppduBw;
1118 while (bw > 20)
1119 {
1120 obssPdLevel += 3;
1121 bw /= 2;
1122 }
1123
1124 return std::max(VhtPhy::GetCcaThreshold(ppdu, channelType), obssPdLevel);
1125}
1126
1127void
1129{
1130 NS_LOG_FUNCTION(this);
1131 const auto ccaIndication = GetCcaIndication(ppdu);
1132 const auto per20MHzDurations = GetPer20MHzDurations(ppdu);
1133 if (ccaIndication.has_value())
1134 {
1135 NS_LOG_DEBUG("CCA busy for " << ccaIndication.value().second << " during "
1136 << ccaIndication.value().first.As(Time::S));
1137 NotifyCcaBusy(ccaIndication.value().first, ccaIndication.value().second, per20MHzDurations);
1138 return;
1139 }
1140 if (ppdu)
1141 {
1142 SwitchMaybeToCcaBusy(nullptr);
1143 return;
1144 }
1145 if (per20MHzDurations != m_lastPer20MHzDurations)
1146 {
1147 /*
1148 * 8.3.5.12.3: For Clause 27 PHYs, this primitive is generated when (...) the per20bitmap
1149 * parameter changes.
1150 */
1151 NS_LOG_DEBUG("per-20MHz CCA durations changed");
1152 NotifyCcaBusy(Seconds(0), WIFI_CHANLIST_PRIMARY, per20MHzDurations);
1153 }
1154}
1155
1156void
1158{
1159 NS_LOG_FUNCTION(this << duration << channelType);
1160 NS_LOG_DEBUG("CCA busy for " << channelType << " during " << duration.As(Time::S));
1161 const auto per20MHzDurations = GetPer20MHzDurations(ppdu);
1162 NotifyCcaBusy(duration, channelType, per20MHzDurations);
1163}
1164
1165void
1167 WifiChannelListType channelType,
1168 const std::vector<Time>& per20MHzDurations)
1169{
1170 NS_LOG_FUNCTION(this << duration << channelType);
1171 m_state->SwitchMaybeToCcaBusy(duration, channelType, per20MHzDurations);
1172 m_lastPer20MHzDurations = per20MHzDurations;
1173}
1174
1175std::vector<Time>
1177{
1178 NS_LOG_FUNCTION(this);
1179
1180 /**
1181 * 27.3.20.6.5 Per 20 MHz CCA sensitivity:
1182 * If the operating channel width is greater than 20 MHz and the PHY issues a PHY-CCA.indication
1183 * primitive, the PHY shall set the per20bitmap to indicate the busy/idle status of each 20 MHz
1184 * subchannel.
1185 */
1186 if (m_wifiPhy->GetChannelWidth() < 40)
1187 {
1188 return {};
1189 }
1190
1191 std::vector<Time> per20MhzDurations{};
1194 for (auto index : indices)
1195 {
1196 auto band = m_wifiPhy->GetBand(20, index);
1197 /**
1198 * A signal is present on the 20 MHz subchannel at or above a threshold of –62 dBm at the
1199 * receiver's antenna(s). The PHY shall indicate that the 20 MHz subchannel is busy a period
1200 * aCCATime after the signal starts and shall continue to indicate the 20 MHz subchannel is
1201 * busy while the threshold continues to be exceeded.
1202 */
1203 double ccaThresholdDbm = -62;
1204 Time delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThresholdDbm, band);
1205
1206 if (ppdu)
1207 {
1208 const uint16_t subchannelMinFreq =
1209 m_wifiPhy->GetFrequency() - (m_wifiPhy->GetChannelWidth() / 2) + (index * 20);
1210 const uint16_t subchannelMaxFreq = subchannelMinFreq + 20;
1211 const uint16_t ppduBw = ppdu->GetTxVector().GetChannelWidth();
1212
1213 if (ppduBw <= m_wifiPhy->GetChannelWidth() &&
1214 ppdu->DoesOverlapChannel(subchannelMinFreq, subchannelMaxFreq))
1215 {
1216 std::optional<double> obssPdLevel{std::nullopt};
1218 {
1219 obssPdLevel = m_obssPdAlgorithm->GetObssPdLevel();
1220 }
1221 switch (ppduBw)
1222 {
1223 case 20:
1224 case 22:
1225 /**
1226 * A 20 MHz non-HT, HT_MF, HT_GF, VHT, or HE PPDU at or above max(–72 dBm, OBSS_
1227 * PDlevel) at the receiver's antenna(s) is present on the 20 MHz subchannel.
1228 * The PHY shall indicate that the 20 MHz subchannel is busy with > 90%
1229 * probability within a period aCCAMidTime.
1230 */
1231 ccaThresholdDbm =
1232 obssPdLevel.has_value() ? std::max(-72.0, obssPdLevel.value()) : -72.0;
1233 band = m_wifiPhy->GetBand(20, index);
1234 break;
1235 case 40:
1236 /**
1237 * The 20 MHz subchannel is in a channel on which a 40 MHz non-HT duplicate,
1238 * HT_MF, HT_GF, VHT or HE PPDU at or above max(–72 dBm, OBSS_PDlevel + 3 dB) at
1239 * the receiver's antenna(s) is present. The PHY shall indicate that the 20 MHz
1240 * subchannel is busy with > 90% probability within a period aCCAMidTime.
1241 */
1242 ccaThresholdDbm =
1243 obssPdLevel.has_value() ? std::max(-72.0, obssPdLevel.value() + 3) : -72.0;
1244 band = m_wifiPhy->GetBand(40, std::floor(index / 2));
1245 break;
1246 case 80:
1247 /**
1248 * The 20 MHz subchannel is in a channel on which an 80 MHz non-HT duplicate,
1249 * VHT or HE PPDU at or above max(–69 dBm, OBSS_PDlevel + 6 dB) at the
1250 * receiver's antenna(s) is present. The PHY shall indicate that the 20 MHz
1251 * subchannel is busy with > 90% probability within a period aCCAMidTime.
1252 */
1253 ccaThresholdDbm =
1254 obssPdLevel.has_value() ? std::max(-69.0, obssPdLevel.value() + 6) : -69.0;
1255 band = m_wifiPhy->GetBand(80, std::floor(index / 4));
1256 break;
1257 case 160:
1258 // Not defined in the standard: keep -62 dBm
1259 break;
1260 default:
1261 NS_ASSERT_MSG(false, "Invalid channel width: " << ppduBw);
1262 }
1263 }
1264 Time ppduCcaDuration = GetDelayUntilCcaEnd(ccaThresholdDbm, band);
1265 delayUntilCcaEnd = std::max(delayUntilCcaEnd, ppduCcaDuration);
1266 }
1267 per20MhzDurations.push_back(delayUntilCcaEnd);
1268 }
1269
1270 return per20MhzDurations;
1271}
1272
1273uint64_t
1275{
1276 NS_LOG_FUNCTION(this << txVector);
1277 uint64_t uid;
1278 if (txVector.IsUlMu() || txVector.IsTriggerResponding())
1279 {
1280 // Use UID of PPDU containing trigger frame to identify resulting HE TB PPDUs, since the
1281 // latter should immediately follow the former
1283 NS_ASSERT(uid != UINT64_MAX);
1284 }
1285 else
1286 {
1287 uid = m_globalPpduUid++;
1288 }
1289 m_previouslyTxPpduUid = uid; // to be able to identify solicited HE TB PPDUs
1290 return uid;
1291}
1292
1293Time
1295{
1296 auto heConfiguration = m_wifiPhy->GetDevice()->GetHeConfiguration();
1297 NS_ASSERT(heConfiguration);
1298 // DoStartReceivePayload(), which is called when we start receiving the Data field,
1299 // computes the max offset among TB PPDUs based on the begin MU payload RX events,
1300 // which are scheduled by StartReceivePreamble() when starting the reception of the
1301 // HE portion. Therefore, the maximum delay cannot exceed the duration of the
1302 // training fields that are between the start of the HE portion and the start
1303 // of the Data field.
1304 auto maxDelay = GetDuration(WIFI_PPDU_FIELD_TRAINING, txVector);
1305 if (heConfiguration->GetMaxTbPpduDelay().IsStrictlyPositive())
1306 {
1307 maxDelay = Min(maxDelay, heConfiguration->GetMaxTbPpduDelay());
1308 }
1309 return maxDelay;
1310}
1311
1314{
1315 auto hePpdu = DynamicCast<const HePpdu>(ppdu);
1316 NS_ASSERT(hePpdu);
1317 HePpdu::TxPsdFlag flag = hePpdu->GetTxPsdFlag();
1318 return GetTxPowerSpectralDensity(txPowerW, ppdu, flag);
1319}
1320
1324 HePpdu::TxPsdFlag flag) const
1325{
1326 const auto& txVector = ppdu->GetTxVector();
1327 uint16_t centerFrequency = GetCenterFrequencyForChannelWidth(txVector);
1328 uint16_t channelWidth = txVector.GetChannelWidth();
1329 NS_LOG_FUNCTION(this << centerFrequency << channelWidth << txPowerW << txVector);
1330 const auto& puncturedSubchannels = txVector.GetInactiveSubchannels();
1331 if (!puncturedSubchannels.empty())
1332 {
1333 const auto p20Index = m_wifiPhy->GetOperatingChannel().GetPrimaryChannelIndex(20);
1334 const auto& indices =
1336 const auto p20IndexInBitmap = p20Index - *(indices.cbegin());
1337 NS_ASSERT(
1338 !puncturedSubchannels.at(p20IndexInBitmap)); // the primary channel cannot be punctured
1339 }
1340 const auto& txMaskRejectionParams = GetTxMaskRejectionParams();
1341 switch (ppdu->GetType())
1342 {
1343 case WIFI_PPDU_TYPE_UL_MU: {
1344 if (flag == HePpdu::PSD_NON_HE_PORTION)
1345 {
1346 // non-HE portion is sent only on the 20 MHz channels covering the RU
1347 const uint16_t staId = GetStaId(ppdu);
1348 centerFrequency = GetCenterFrequencyForNonHePart(txVector, staId);
1349 const uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
1350 channelWidth = (ruWidth < 20) ? 20 : ruWidth;
1352 centerFrequency,
1353 channelWidth,
1354 txPowerW,
1355 GetGuardBandwidth(channelWidth),
1356 std::get<0>(txMaskRejectionParams),
1357 std::get<1>(txMaskRejectionParams),
1358 std::get<2>(txMaskRejectionParams),
1359 puncturedSubchannels);
1360 }
1361 else
1362 {
1363 const auto band = GetRuBandForTx(txVector, GetStaId(ppdu)).indices;
1365 centerFrequency,
1366 channelWidth,
1367 txPowerW,
1368 GetGuardBandwidth(channelWidth),
1369 band);
1370 }
1371 }
1372 case WIFI_PPDU_TYPE_DL_MU: {
1373 if (flag == HePpdu::PSD_NON_HE_PORTION)
1374 {
1376 centerFrequency,
1377 channelWidth,
1378 txPowerW,
1379 GetGuardBandwidth(channelWidth),
1380 std::get<0>(txMaskRejectionParams),
1381 std::get<1>(txMaskRejectionParams),
1382 std::get<2>(txMaskRejectionParams),
1383 puncturedSubchannels);
1384 }
1385 else
1386 {
1388 centerFrequency,
1389 channelWidth,
1390 txPowerW,
1391 GetGuardBandwidth(channelWidth),
1392 std::get<0>(txMaskRejectionParams),
1393 std::get<1>(txMaskRejectionParams),
1394 std::get<2>(txMaskRejectionParams),
1395 puncturedSubchannels);
1396 }
1397 }
1398 case WIFI_PPDU_TYPE_SU:
1399 default: {
1400 NS_ASSERT(puncturedSubchannels.empty());
1402 centerFrequency,
1403 channelWidth,
1404 txPowerW,
1405 GetGuardBandwidth(channelWidth),
1406 std::get<0>(txMaskRejectionParams),
1407 std::get<1>(txMaskRejectionParams),
1408 std::get<2>(txMaskRejectionParams));
1409 }
1410 }
1411}
1412
1413uint16_t
1414HePhy::GetCenterFrequencyForNonHePart(const WifiTxVector& txVector, uint16_t staId) const
1415{
1416 NS_LOG_FUNCTION(this << txVector << staId);
1417 NS_ASSERT(txVector.IsUlMu() && (txVector.GetModulationClass() >= WIFI_MOD_CLASS_HE));
1418 uint16_t centerFrequency = GetCenterFrequencyForChannelWidth(txVector);
1419 uint16_t currentWidth = txVector.GetChannelWidth();
1420
1421 HeRu::RuSpec ru = txVector.GetRu(staId);
1422 uint16_t nonOfdmaWidth = GetNonOfdmaWidth(ru);
1423 if (nonOfdmaWidth != currentWidth)
1424 {
1425 // Obtain the index of the non-OFDMA portion
1426 HeRu::RuSpec nonOfdmaRu =
1427 HeRu::FindOverlappingRu(currentWidth, ru, HeRu::GetRuType(nonOfdmaWidth));
1428
1429 uint16_t startingFrequency = centerFrequency - (currentWidth / 2);
1430 centerFrequency =
1431 startingFrequency +
1432 nonOfdmaWidth * (nonOfdmaRu.GetPhyIndex(
1433 currentWidth,
1435 1) +
1436 nonOfdmaWidth / 2;
1437 }
1438 return centerFrequency;
1439}
1440
1441void
1443{
1444 NS_LOG_FUNCTION(this << ppdu);
1445 const auto& txVector = ppdu->GetTxVector();
1446 if (auto mac = m_wifiPhy->GetDevice()->GetMac(); mac && (mac->GetTypeOfStation() == AP))
1447 {
1448 m_currentTxVector = txVector;
1449 }
1450 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU || ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
1451 {
1452 auto nonHeTxPowerDbm = m_wifiPhy->GetTxPowerForTransmission(ppdu) + m_wifiPhy->GetTxGain();
1453
1454 // temporarily set WifiPpdu flag to PSD_HE_PORTION for correct calculation of TX power for
1455 // the HE portion
1456 auto hePpdu = DynamicCast<const HePpdu>(ppdu);
1457 NS_ASSERT(hePpdu);
1458 hePpdu->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
1459 auto heTxPowerDbm = m_wifiPhy->GetTxPowerForTransmission(ppdu) + m_wifiPhy->GetTxGain();
1460 hePpdu->SetTxPsdFlag(HePpdu::PSD_NON_HE_PORTION);
1461
1462 // non-HE portion
1463 auto nonHePortionDuration = ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU
1466 auto nonHeTxPowerSpectrum =
1468 Transmit(nonHePortionDuration,
1469 ppdu,
1470 nonHeTxPowerDbm,
1471 nonHeTxPowerSpectrum,
1472 "non-HE portion transmission");
1473
1474 // HE portion
1475 auto hePortionDuration = ppdu->GetTxDuration() - nonHePortionDuration;
1476 auto heTxPowerSpectrum =
1478 Simulator::Schedule(nonHePortionDuration,
1480 this,
1481 ppdu,
1482 heTxPowerDbm,
1483 heTxPowerSpectrum,
1484 hePortionDuration);
1485 }
1486 else
1487 {
1488 VhtPhy::StartTx(ppdu);
1489 }
1490}
1491
1492void
1494 double txPowerDbm,
1495 Ptr<SpectrumValue> txPowerSpectrum,
1496 Time hePortionDuration)
1497{
1498 NS_LOG_FUNCTION(this << ppdu << txPowerDbm << hePortionDuration);
1499 auto hePpdu = DynamicCast<const HePpdu>(ppdu);
1500 NS_ASSERT(hePpdu);
1501 hePpdu->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
1502 Transmit(hePortionDuration, ppdu, txPowerDbm, txPowerSpectrum, "HE portion transmission");
1503}
1504
1505Time
1507 const WifiTxVector& txVector,
1508 WifiPhyBand band) const
1509{
1510 if (txVector.IsUlMu())
1511 {
1513 return ConvertLSigLengthToHeTbPpduDuration(txVector.GetLength(), txVector, band);
1514 }
1515
1516 Time maxDuration = Seconds(0);
1517 for (auto& staIdPsdu : psduMap)
1518 {
1519 if (txVector.IsDlMu())
1520 {
1522 NS_ABORT_MSG_IF(!txVector.GetHeMuUserInfoMap().contains(staIdPsdu.first),
1523 "STA-ID in psduMap (" << staIdPsdu.first
1524 << ") should be referenced in txVector");
1525 }
1526 Time current = WifiPhy::CalculateTxDuration(staIdPsdu.second->GetSize(),
1527 txVector,
1528 band,
1529 staIdPsdu.first);
1530 if (current > maxDuration)
1531 {
1532 maxDuration = current;
1533 }
1534 }
1535 NS_ASSERT(maxDuration.IsStrictlyPositive());
1536 return maxDuration;
1537}
1538
1539void
1541{
1542 for (uint8_t i = 0; i < 12; ++i)
1543 {
1544 GetHeMcs(i);
1545 }
1546}
1547
1549HePhy::GetHeMcs(uint8_t index)
1550{
1551#define CASE(x) \
1552 case x: \
1553 return GetHeMcs##x();
1554
1555 switch (index)
1556 {
1557 CASE(0)
1558 CASE(1)
1559 CASE(2)
1560 CASE(3)
1561 CASE(4)
1562 CASE(5)
1563 CASE(6)
1564 CASE(7)
1565 CASE(8)
1566 CASE(9)
1567 CASE(10)
1568 CASE(11)
1569 default:
1570 NS_ABORT_MSG("Inexistent index (" << +index << ") requested for HE");
1571 return WifiMode();
1572 }
1573#undef CASE
1574}
1575
1576#define GET_HE_MCS(x) \
1577 WifiMode HePhy::GetHeMcs##x() \
1578 { \
1579 static WifiMode mcs = CreateHeMcs(x); \
1580 return mcs; \
1581 }
1582
1583GET_HE_MCS(0)
1584GET_HE_MCS(1)
1585GET_HE_MCS(2)
1586GET_HE_MCS(3)
1587GET_HE_MCS(4)
1588GET_HE_MCS(5)
1589GET_HE_MCS(6)
1590GET_HE_MCS(7)
1591GET_HE_MCS(8)
1592GET_HE_MCS(9)
1593GET_HE_MCS(10)
1594GET_HE_MCS(11)
1595#undef GET_HE_MCS
1596
1597WifiMode
1599{
1600 NS_ASSERT_MSG(index <= 11, "HeMcs index must be <= 11!");
1601 return WifiModeFactory::CreateWifiMcs("HeMcs" + std::to_string(index),
1602 index,
1604 false,
1611}
1612
1614HePhy::GetCodeRate(uint8_t mcsValue)
1615{
1616 switch (mcsValue)
1617 {
1618 case 10:
1619 return WIFI_CODE_RATE_3_4;
1620 case 11:
1621 return WIFI_CODE_RATE_5_6;
1622 default:
1623 return VhtPhy::GetCodeRate(mcsValue);
1624 }
1625}
1626
1627uint16_t
1629{
1630 switch (mcsValue)
1631 {
1632 case 10:
1633 case 11:
1634 return 1024;
1635 default:
1636 return VhtPhy::GetConstellationSize(mcsValue);
1637 }
1638}
1639
1640uint64_t
1641HePhy::GetPhyRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
1642{
1643 WifiCodeRate codeRate = GetCodeRate(mcsValue);
1644 uint64_t dataRate = GetDataRate(mcsValue, channelWidth, guardInterval, nss);
1645 return HtPhy::CalculatePhyRate(codeRate, dataRate);
1646}
1647
1648uint64_t
1649HePhy::GetPhyRateFromTxVector(const WifiTxVector& txVector, uint16_t staId /* = SU_STA_ID */)
1650{
1651 uint16_t bw = txVector.GetChannelWidth();
1652 if (txVector.IsMu())
1653 {
1654 bw = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
1655 }
1656 return HePhy::GetPhyRate(txVector.GetMode(staId).GetMcsValue(),
1657 bw,
1658 txVector.GetGuardInterval(),
1659 txVector.GetNss(staId));
1660}
1661
1662uint64_t
1663HePhy::GetDataRateFromTxVector(const WifiTxVector& txVector, uint16_t staId /* = SU_STA_ID */)
1664{
1665 uint16_t bw = txVector.GetChannelWidth();
1666 if (txVector.IsMu())
1667 {
1668 bw = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
1669 }
1670 return HePhy::GetDataRate(txVector.GetMode(staId).GetMcsValue(),
1671 bw,
1672 txVector.GetGuardInterval(),
1673 txVector.GetNss(staId));
1674}
1675
1676uint64_t
1677HePhy::GetDataRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
1678{
1679 NS_ASSERT(guardInterval == 800 || guardInterval == 1600 || guardInterval == 3200);
1680 NS_ASSERT(nss <= 8);
1682 GetUsableSubcarriers(channelWidth),
1683 static_cast<uint16_t>(log2(GetConstellationSize(mcsValue))),
1685 nss);
1686}
1687
1688uint16_t
1689HePhy::GetUsableSubcarriers(uint16_t channelWidth)
1690{
1691 switch (channelWidth)
1692 {
1693 case 2: // 26-tone RU
1694 return 24;
1695 case 4: // 52-tone RU
1696 return 48;
1697 case 8: // 106-tone RU
1698 return 102;
1699 case 20:
1700 default:
1701 return 234;
1702 case 40:
1703 return 468;
1704 case 80:
1705 return 980;
1706 case 160:
1707 return 1960;
1708 }
1709}
1710
1711Time
1713{
1714 return NanoSeconds(12800) + guardInterval;
1715}
1716
1717uint64_t
1719{
1720 WifiCodeRate codeRate = GetCodeRate(mcsValue);
1721 uint16_t constellationSize = GetConstellationSize(mcsValue);
1722 return CalculateNonHtReferenceRate(codeRate, constellationSize);
1723}
1724
1725uint64_t
1726HePhy::CalculateNonHtReferenceRate(WifiCodeRate codeRate, uint16_t constellationSize)
1727{
1728 uint64_t dataRate;
1729 switch (constellationSize)
1730 {
1731 case 1024:
1732 if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6)
1733 {
1734 dataRate = 54000000;
1735 }
1736 else
1737 {
1738 NS_FATAL_ERROR("Trying to get reference rate for a MCS with wrong combination of "
1739 "coding rate and modulation");
1740 }
1741 break;
1742 default:
1743 dataRate = VhtPhy::CalculateNonHtReferenceRate(codeRate, constellationSize);
1744 }
1745 return dataRate;
1746}
1747
1748bool
1749HePhy::IsAllowed(const WifiTxVector& /*txVector*/)
1750{
1751 return true;
1752}
1753
1756{
1757 uint16_t staId = SU_STA_ID;
1758
1759 if (IsUlMu(txVector.GetPreambleType()))
1760 {
1761 NS_ASSERT(txVector.GetHeMuUserInfoMap().size() == 1);
1762 staId = txVector.GetHeMuUserInfoMap().begin()->first;
1763 }
1764
1765 return WifiConstPsduMap({{staId, psdu}});
1766}
1767
1770{
1771 return 6500631;
1772}
1773
1774bool
1776{
1777 /*
1778 * The PHY shall not issue a PHY-RXSTART.indication primitive in response to a PPDU
1779 * that does not overlap the primary channel, unless the PHY at an AP receives the
1780 * HE TB PPDU solicited by the AP. For the HE TB PPDU solicited by the AP, the PHY
1781 * shall issue a PHY-RXSTART.indication primitive for a PPDU received in the primary
1782 * or at the secondary 20 MHz channel, the secondary 40 MHz channel, or the secondary
1783 * 80 MHz channel.
1784 */
1785 Ptr<WifiMac> mac = m_wifiPhy->GetDevice() ? m_wifiPhy->GetDevice()->GetMac() : nullptr;
1786 if (ppdu->GetTxVector().IsUlMu() && mac && mac->GetTypeOfStation() == AP)
1787 {
1788 return true;
1789 }
1790 return VhtPhy::CanStartRx(ppdu);
1791}
1792
1795{
1796 if (ppdu->GetType() == WIFI_PPDU_TYPE_UL_MU)
1797 {
1798 Ptr<const WifiPpdu> rxPpdu;
1799 if ((m_trigVectorExpirationTime.has_value()) &&
1801 {
1802 // We only copy if the AP that is expecting a HE TB PPDU, since the content
1803 // of the TXVECTOR is reconstructed from the TRIGVECTOR, hence the other RX
1804 // PHYs should not have this information.
1805 rxPpdu = ppdu->Copy();
1806 }
1807 else
1808 {
1809 rxPpdu = ppdu;
1810 }
1811 auto hePpdu = DynamicCast<const HePpdu>(rxPpdu);
1812 NS_ASSERT(hePpdu);
1813 hePpdu->UpdateTxVectorForUlMu(m_trigVector);
1814 return rxPpdu;
1815 }
1816 return VhtPhy::GetRxPpduFromTxPpdu(ppdu);
1817}
1818
1821 uint16_t guardBandwidth,
1822 uint32_t subcarrierSpacing,
1823 HeRu::SubcarrierRange subcarrierRange,
1824 uint8_t bandIndex)
1825{
1826 WifiSpectrumBandIndices convertedSubcarriers;
1827 auto nGuardBands =
1828 static_cast<uint32_t>(((2 * guardBandwidth * 1e6) / subcarrierSpacing) + 0.5);
1829 uint32_t centerFrequencyIndex = 0;
1830 switch (bandWidth)
1831 {
1832 case 20:
1833 centerFrequencyIndex = (nGuardBands / 2) + 6 + 122;
1834 break;
1835 case 40:
1836 centerFrequencyIndex = (nGuardBands / 2) + 12 + 244;
1837 break;
1838 case 80:
1839 centerFrequencyIndex = (nGuardBands / 2) + 12 + 500;
1840 break;
1841 case 160:
1842 centerFrequencyIndex = (nGuardBands / 2) + 12 + 1012;
1843 break;
1844 default:
1845 NS_FATAL_ERROR("ChannelWidth " << bandWidth << " unsupported");
1846 break;
1847 }
1848
1849 auto numBandsInBand = static_cast<size_t>(bandWidth * 1e6 / subcarrierSpacing);
1850 centerFrequencyIndex += numBandsInBand * bandIndex;
1851
1852 convertedSubcarriers.first = centerFrequencyIndex + subcarrierRange.first;
1853 convertedSubcarriers.second = centerFrequencyIndex + subcarrierRange.second;
1854 return convertedSubcarriers;
1855}
1856
1857} // namespace ns3
1858
1859namespace
1860{
1861
1862/**
1863 * Constructor class for HE modes
1864 */
1866{
1867 public:
1869 {
1871 ns3::WifiPhy::AddStaticPhyEntity(ns3::WIFI_MOD_CLASS_HE, ns3::Create<ns3::HePhy>());
1872 }
1873} g_constructor_he; ///< the constructor for HE modes
1874
1875} // namespace
#define Max(a, b)
#define Min(a, b)
Constructor class for HE modes.
Definition: he-phy.cc:1866
bool IsNull() const
Check for null implementation.
Definition: callback.h:571
std::optional< WifiTxVector > m_trigVector
the TRIGVECTOR
Definition: he-phy.h:565
Time GetLSigDuration(WifiPreamble preamble) const override
Definition: he-phy.cc:188
virtual Time CalculateNonHeDurationForHeTb(const WifiTxVector &txVector) const
Definition: he-phy.cc:305
static Time ConvertLSigLengthToHeTbPpduDuration(uint16_t length, const WifiTxVector &txVector, WifiPhyBand band)
Definition: he-phy.cc:291
uint16_t GetCenterFrequencyForNonHePart(const WifiTxVector &txVector, uint16_t staId) const
Get the center frequency of the non-HE portion of the current TxVector for the given STA-ID.
Definition: he-phy.cc:1414
uint64_t GetCurrentHeTbPpduUid() const
Definition: he-phy.cc:1074
Ptr< Event > DoGetEvent(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW) override
Get the event corresponding to the incoming PPDU.
Definition: he-phy.cc:460
void CancelAllEvents() override
Cancel and clear all running events.
Definition: he-phy.cc:415
void SetObssPdAlgorithm(const Ptr< ObssPdAlgorithm > algorithm)
Sets the OBSS-PD algorithm.
Definition: he-phy.cc:703
static void InitializeModes()
Initialize all HE modes.
Definition: he-phy.cc:1540
void DoAbortCurrentReception(WifiPhyRxfailureReason reason) override
Perform amendment-specific actions before aborting the current reception.
Definition: he-phy.cc:427
WifiSpectrumBandInfo GetRuBandForRx(const WifiTxVector &txVector, uint16_t staId) const
Get the band in the RX spectrum associated with the RU used by the PSDU transmitted to/by a given STA...
Definition: he-phy.cc:1010
Time CalculateTxDuration(WifiConstPsduMap psduMap, const WifiTxVector &txVector, WifiPhyBand band) const override
Definition: he-phy.cc:1506
void StartReceiveMuPayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: he-phy.cc:933
virtual PhyFieldRxStatus ProcessSigB(Ptr< Event > event, PhyFieldRxStatus status)
Process SIG-B, perform amendment-specific actions, and provide an updated status of the reception.
Definition: he-phy.cc:730
virtual Time CalculateNonHeDurationForHeMu(const WifiTxVector &txVector) const
Definition: he-phy.cc:314
std::optional< WifiTxVector > m_currentTxVector
If the STA is an AP STA, this holds the TXVECTOR of the PPDU that has been sent.
Definition: he-phy.h:567
Time GetSigBDuration(const WifiTxVector &txVector) const override
Definition: he-phy.cc:239
static WifiMode CreateHeMcs(uint8_t index)
Create and return the HE MCS corresponding to the provided index.
Definition: he-phy.cc:1598
virtual uint32_t GetSigBSize(const WifiTxVector &txVector) const
Definition: he-phy.cc:223
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition: he-phy.cc:1549
void BuildModeList() override
Build mode list.
Definition: he-phy.cc:107
WifiConstPsduMap GetWifiConstPsduMap(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) const override
Get a WifiConstPsduMap from a PSDU and the TXVECTOR to use to send the PSDU.
Definition: he-phy.cc:1755
uint16_t GetNonOfdmaWidth(HeRu::RuSpec ru) const
Get the width in MHz of the non-OFDMA portion of an HE TB PPDU.
Definition: he-phy.cc:1062
static uint64_t CalculateNonHtReferenceRate(WifiCodeRate codeRate, uint16_t constellationSize)
Return the rate (in bps) of the non-HT Reference Rate which corresponds to the supplied code rate and...
Definition: he-phy.cc:1726
bool CanStartRx(Ptr< const WifiPpdu > ppdu) const override
Determine whether the PHY shall issue a PHY-RXSTART.indication primitive in response to a given PPDU.
Definition: he-phy.cc:1775
void StartTxHePortion(Ptr< const WifiPpdu > ppdu, double txPowerDbm, Ptr< SpectrumValue > txPowerSpectrum, Time hePortionDuration)
Start the transmission of the HE portion of the MU PPDU.
Definition: he-phy.cc:1493
void SetEndOfHeSigACallback(EndOfHeSigACallback callback)
Set a callback for a end of HE-SIG-A.
Definition: he-phy.cc:715
uint64_t m_previouslyTxPpduUid
UID of the previously sent PPDU, used by AP to recognize response HE TB PPDUs.
Definition: he-phy.h:556
static WifiCodeRate GetCodeRate(uint8_t mcsValue)
Return the coding rate corresponding to the supplied HE MCS index.
Definition: he-phy.cc:1614
void StartTx(Ptr< const WifiPpdu > ppdu) override
This function is called by SpectrumWifiPhy to send the PPDU while performing amendment-specific actio...
Definition: he-phy.cc:1442
PhyFieldRxStatus ProcessSig(Ptr< Event > event, PhyFieldRxStatus status, WifiPpduField field) override
Process SIG-A or SIG-B, perform amendment-specific actions, and provide an updated status of the rece...
Definition: he-phy.cc:593
EndOfHeSigACallback m_endOfHeSigACallback
end of HE-SIG-A callback
Definition: he-phy.h:564
Ptr< const WifiPsdu > GetAddressedPsduInPpdu(Ptr< const WifiPpdu > ppdu) const override
Get the PSDU addressed to that PHY in a PPDU (useful for MU PPDU).
Definition: he-phy.cc:548
WifiMode GetSigMode(WifiPpduField field, const WifiTxVector &txVector) const override
Get the WifiMode for the SIG field specified by the PPDU field.
Definition: he-phy.cc:120
const PpduFormats & GetPpduFormats() const override
Return the PPDU formats of the PHY.
Definition: he-phy.cc:182
uint64_t ObtainNextUid(const WifiTxVector &txVector) override
Obtain the next UID for the PPDU to transmit.
Definition: he-phy.cc:1274
static uint64_t GetPhyRateFromTxVector(const WifiTxVector &txVector, uint16_t staId=SU_STA_ID)
Return the PHY rate corresponding to the supplied TXVECTOR for the STA-ID.
Definition: he-phy.cc:1649
Ptr< ObssPdAlgorithm > m_obssPdAlgorithm
OBSS-PD algorithm.
Definition: he-phy.h:640
Ptr< ObssPdAlgorithm > GetObssPdAlgorithm() const
Gets the OBSS-PD algorithm.
Definition: he-phy.cc:709
uint8_t GetBssColor() const
Definition: he-phy.cc:560
static Time GetValidPpduDuration(Time ppduDuration, const WifiTxVector &txVector, WifiPhyBand band)
Given a PPDU duration value, the TXVECTOR used to transmit the PPDU and the PHY band,...
Definition: he-phy.cc:259
static WifiSpectrumBandIndices ConvertHeRuSubcarriers(uint16_t bandWidth, uint16_t guardBandwidth, uint32_t subcarrierSpacing, HeRu::SubcarrierRange subcarrierRange, uint8_t bandIndex=0)
Definition: he-phy.cc:1820
uint8_t GetNumberBccEncoders(const WifiTxVector &txVector) const override
Definition: he-phy.cc:324
Time GetMaxDelayPpduSameUid(const WifiTxVector &txVector) override
Obtain the maximum time between two PPDUs with the same UID to consider they are identical and their ...
Definition: he-phy.cc:1294
void HandleRxPpduWithSameContent(Ptr< Event > event, Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPower) override
Handle reception of a PPDU that carries the same content of another PPDU.
Definition: he-phy.cc:526
static bool IsAllowed(const WifiTxVector &txVector)
Check whether the combination in TXVECTOR is allowed.
Definition: he-phy.cc:1749
std::size_t m_rxHeTbPpdus
Number of successfully received HE TB PPDUS.
Definition: he-phy.h:639
~HePhy() override
Destructor for HE PHY.
Definition: he-phy.cc:101
Ptr< WifiPpdu > BuildPpdu(const WifiConstPsduMap &psdus, const WifiTxVector &txVector, Time ppduDuration) override
Build amendment-specific PPDU.
Definition: he-phy.cc:353
void NotifyEndOfHeSigA(HeSigAParameters params)
Fire a EndOfHeSigA callback (if connected) once HE-SIG-A field has been received.
Definition: he-phy.cc:721
static uint64_t GetDataRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
Return the data rate corresponding to the supplied HE MCS index, channel width, guard interval,...
Definition: he-phy.cc:1677
void RxPayloadSucceeded(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, uint16_t staId, const std::vector< bool > &statusPerMpdu) override
Perform amendment-specific actions when the payload is successfully received.
Definition: he-phy.cc:861
static uint64_t GetPhyRate(uint8_t mcsValue, uint16_t channelWidth, uint16_t guardInterval, uint8_t nss)
Return the PHY rate corresponding to the supplied HE MCS index, channel width, guard interval,...
Definition: he-phy.cc:1641
uint64_t m_currentMuPpduUid
UID of the HE MU or HE TB PPDU being received.
Definition: he-phy.h:558
uint32_t GetMaxPsduSize() const override
Get the maximum PSDU size in bytes.
Definition: he-phy.cc:1769
static const PpduFormats m_hePpduFormats
HE PPDU formats.
Definition: he-phy.h:637
static uint64_t GetDataRateFromTxVector(const WifiTxVector &txVector, uint16_t staId=SU_STA_ID)
Return the data rate corresponding to the supplied TXVECTOR for the STA-ID.
Definition: he-phy.cc:1663
std::map< uint16_t, EventId > m_beginMuPayloadRxEvents
the beginning of the MU payload reception events (indexed by STA-ID)
Definition: he-phy.h:561
std::vector< Time > GetPer20MHzDurations(const Ptr< const WifiPpdu > ppdu)
Compute the per-20 MHz CCA durations vector that indicates for how long each 20 MHz subchannel (corre...
Definition: he-phy.cc:1176
void RxPayloadFailed(Ptr< const WifiPsdu > psdu, double snr, const WifiTxVector &txVector) override
Perform amendment-specific actions when the payload is unsuccessfuly received.
Definition: he-phy.cc:879
double GetCcaThreshold(const Ptr< const WifiPpdu > ppdu, WifiChannelListType channelType) const override
Return the CCA threshold in dBm for a given channel type.
Definition: he-phy.cc:1098
Ptr< const WifiPpdu > GetRxPpduFromTxPpdu(Ptr< const WifiPpdu > ppdu) override
The WifiPpdu from the TX PHY is received by each RX PHY attached to the same channel.
Definition: he-phy.cc:1794
HePhy(bool buildModeList=true)
Constructor for HE PHY.
Definition: he-phy.cc:81
bool IsConfigSupported(Ptr< const WifiPpdu > ppdu) const override
Checks if the signaled configuration (excluding bandwidth) is supported by the PHY.
Definition: he-phy.cc:752
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
Definition: he-phy.cc:575
static Time GetSymbolDuration(Time guardInterval)
Definition: he-phy.cc:1712
std::pair< uint16_t, WifiSpectrumBandInfo > GetChannelWidthAndBand(const WifiTxVector &txVector, uint16_t staId) const override
Get the channel width and band to use (will be overloaded by child classes).
Definition: he-phy.cc:974
void SetTrigVector(const WifiTxVector &trigVector, Time validity)
Set the TRIGVECTOR and the associated expiration time.
Definition: he-phy.cc:338
static std::pair< uint16_t, Time > ConvertHeTbPpduDurationToLSigLength(Time ppduDuration, const WifiTxVector &txVector, WifiPhyBand band)
Compute the L-SIG length value corresponding to the given HE TB PPDU duration.
Definition: he-phy.cc:272
static uint64_t GetNonHtReferenceRate(uint8_t mcsValue)
Calculate the rate in bps of the non-HT Reference Rate corresponding to the supplied HE MCS index.
Definition: he-phy.cc:1718
WifiMode GetSigBMode(const WifiTxVector &txVector) const override
Definition: he-phy.cc:149
void SwitchMaybeToCcaBusy(const Ptr< const WifiPpdu > ppdu) override
Check if PHY state should move to CCA busy state based on current state of interference tracker.
Definition: he-phy.cc:1128
Time DoStartReceivePayload(Ptr< Event > event) override
Start receiving the PSDU (i.e.
Definition: he-phy.cc:791
void StartReceivePreamble(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration) override
Start receiving the PHY preamble of a PPDU (i.e.
Definition: he-phy.cc:365
virtual PhyFieldRxStatus ProcessSigA(Ptr< Event > event, PhyFieldRxStatus status)
Process SIG-A, perform amendment-specific actions, and provide an updated status of the reception.
Definition: he-phy.cc:610
std::optional< Time > m_trigVectorExpirationTime
expiration time of the TRIGVECTOR
Definition: he-phy.h:566
void DoEndReceivePayload(Ptr< const WifiPpdu > ppdu) override
Perform amendment-specific actions at the end of the reception of the payload.
Definition: he-phy.cc:889
void DoResetReceive(Ptr< Event > event) override
Perform amendment-specific actions before resetting PHY at the end of the PPDU under reception after ...
Definition: he-phy.cc:445
WifiMode GetSigAMode() const override
Definition: he-phy.cc:143
Time GetSigADuration(WifiPreamble preamble) const override
Definition: he-phy.cc:215
WifiSpectrumBandInfo GetNonOfdmaBand(const WifiTxVector &txVector, uint16_t staId) const
Get the band used to transmit the non-OFDMA part of an HE TB PPDU.
Definition: he-phy.cc:1033
Time GetTrainingDuration(const WifiTxVector &txVector, uint8_t nDataLtf, uint8_t nExtensionLtf=0) const override
Definition: he-phy.cc:194
std::vector< Time > m_lastPer20MHzDurations
Hold the last per-20 MHz CCA durations vector.
Definition: he-phy.h:641
void NotifyCcaBusy(const Ptr< const WifiPpdu > ppdu, Time duration, WifiChannelListType channelType) override
Notify PHY state helper to switch to CCA busy state,.
Definition: he-phy.cc:1157
Ptr< SpectrumValue > GetTxPowerSpectralDensity(double txPowerW, Ptr< const WifiPpdu > ppdu) const override
Definition: he-phy.cc:1313
uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const override
Return the channel width used to measure the RSSI.
Definition: he-phy.cc:1080
static uint16_t GetConstellationSize(uint8_t mcsValue)
Return the constellation size corresponding to the supplied HE MCS index.
Definition: he-phy.cc:1628
WifiSpectrumBandInfo GetRuBandForTx(const WifiTxVector &txVector, uint16_t staId) const
Get the band in the TX spectrum associated with the RU used by the PSDU transmitted to/by a given STA...
Definition: he-phy.cc:988
TxPsdFlag
The transmit power spectral density flag, namely used to correctly build PSDs for pre-HE and HE porti...
Definition: he-ppdu.h:115
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition: he-ppdu.h:117
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
Definition: he-ppdu.h:116
static uint32_t GetSigBFieldSize(uint16_t channelWidth, const RuAllocation &ruAllocation, bool sigBCompression, std::size_t numMuMimoUsers)
Get variable length HE SIG-B field size.
Definition: he-ppdu.cc:639
RU Specification.
Definition: he-ru.h:66
std::size_t GetIndex() const
Get the RU index.
Definition: he-ru.cc:465
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:458
std::size_t GetPhyIndex(uint16_t bw, uint8_t p20Index) const
Get the RU PHY index.
Definition: he-ru.cc:479
static RuSpec FindOverlappingRu(uint16_t bw, RuSpec referenceRu, RuType searchedRuType)
Find the RU allocation of the given RU type overlapping the given reference RU allocation.
Definition: he-ru.cc:689
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:767
static SubcarrierGroup GetSubcarrierGroup(uint16_t bw, RuType ruType, std::size_t phyIndex)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
Definition: he-ru.cc:591
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition: he-ru.h:55
std::pair< int16_t, int16_t > SubcarrierRange
(lowest index, highest index) pair defining a subcarrier range
Definition: he-ru.h:52
@ RU_26_TONE
Definition: he-ru.h:42
static RuType GetRuType(uint16_t bandwidth)
Get the RU corresponding to the approximate bandwidth.
Definition: he-ru.cc:792
static uint64_t CalculatePhyRate(WifiCodeRate codeRate, uint64_t dataRate)
Return the PHY rate corresponding to the supplied code rate and data rate.
Definition: ht-phy.cc:660
uint8_t m_bssMembershipSelector
the BSS membership selector
Definition: ht-phy.h:561
uint8_t m_maxMcsIndexPerSs
the maximum MCS index per spatial stream as defined by the standard
Definition: ht-phy.h:559
static uint64_t CalculateDataRate(Time symbolDuration, uint16_t usableSubCarriers, uint16_t numberOfBitsPerSubcarrier, double codingRate, uint8_t nss)
Calculates data rate from the supplied parameters.
Definition: ht-phy.cc:708
static double GetCodeRatio(WifiCodeRate codeRate)
Convert WifiCodeRate to a ratio, e.g., code ratio of WIFI_CODE_RATE_1_2 is 0.5.
Definition: ht-phy.cc:675
uint8_t m_maxSupportedMcsIndexPerSs
the maximum supported MCS index per spatial stream
Definition: ht-phy.h:560
double GetObssPdLevel() const
static uint16_t GetUsableSubcarriers()
Definition: ofdm-phy.cc:634
Ptr< const WifiPpdu > GetRxPpduFromTxPpdu(Ptr< const WifiPpdu > ppdu) override
The WifiPpdu from the TX PHY is received by each RX PHY attached to the same channel.
Definition: ofdm-phy.cc:691
uint16_t GetMeasurementChannelWidth(const Ptr< const WifiPpdu > ppdu) const override
Return the channel width used to measure the RSSI.
Definition: ofdm-phy.cc:668
void NotifyPayloadBegin(const WifiTxVector &txVector, const Time &payloadDuration)
Fire the trace indicating that the PHY is starting to receive the payload of a PPDU.
Definition: phy-entity.cc:1311
virtual void HandleRxPpduWithSameContent(Ptr< Event > event, Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPower)
Handle reception of a PPDU that carries the same content of another PPDU.
Definition: phy-entity.cc:885
Ptr< WifiPhyStateHelper > m_state
Pointer to WifiPhyStateHelper of the WifiPhy (to make it reachable for child classes)
Definition: phy-entity.h:982
std::tuple< double, double, double > GetTxMaskRejectionParams() const
Definition: phy-entity.cc:1357
virtual Time DoStartReceivePayload(Ptr< Event > event)
Start receiving the PSDU (i.e.
Definition: phy-entity.cc:573
Time GetDelayUntilCcaEnd(double thresholdDbm, const WifiSpectrumBandInfo &band)
Return the delay until CCA busy is ended for a given sensitivity threshold (in dBm) and a given band.
Definition: phy-entity.cc:1235
virtual void StartReceivePreamble(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW, Time rxDuration)
Start receiving the PHY preamble of a PPDU (i.e.
Definition: phy-entity.cc:400
const std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents() const
Get the map of current preamble events (stored in WifiPhy).
Definition: phy-entity.cc:837
std::map< UidStaIdPair, SignalNoiseDbm > m_signalNoiseMap
Map of the latest signal power and noise power in dBm (noise power includes the noise figure)
Definition: phy-entity.h:1002
Ptr< WifiPhy > m_wifiPhy
Pointer to the owning WifiPhy.
Definition: phy-entity.h:981
void Transmit(Time txDuration, Ptr< const WifiPpdu > ppdu, double txPowerDbm, Ptr< SpectrumValue > txPowerSpectrum, const std::string &type)
This function prepares most of the WifiSpectrumSignalParameters parameters and invokes SpectrumWifiPh...
Definition: phy-entity.cc:1327
std::vector< EventId > m_endOfMpduEvents
the end of MPDU events (only used for A-MPDUs)
Definition: phy-entity.h:988
virtual void CancelAllEvents()
Cancel and clear all running events.
Definition: phy-entity.cc:1108
virtual void DoAbortCurrentReception(WifiPhyRxfailureReason reason)
Perform amendment-specific actions before aborting the current reception.
Definition: phy-entity.cc:1150
void EndReceivePayload(Ptr< Event > event)
The last symbol of the PPDU has arrived.
Definition: phy-entity.cc:694
std::map< WifiPreamble, std::vector< WifiPpduField > > PpduFormats
A map of PPDU field elements per preamble type.
Definition: phy-entity.h:561
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:1005
std::vector< EventId > m_endRxPayloadEvents
the end of receive events (only one unless UL MU reception)
Definition: phy-entity.h:991
virtual Ptr< Event > DoGetEvent(Ptr< const WifiPpdu > ppdu, RxPowerWattPerChannelBand &rxPowersW)
Get the event corresponding to the incoming PPDU.
Definition: phy-entity.cc:851
double GetRxPowerWForPpdu(Ptr< Event > event) const
Obtain the received power (W) for a given band.
Definition: phy-entity.cc:1191
Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector) const
Definition: phy-entity.cc:203
void NotifyInterferenceRxEndAndClear(bool reset)
Notify WifiPhy's InterferenceHelper of the end of the reception, clear maps and end of MPDU event,...
Definition: phy-entity.cc:917
std::map< UidStaIdPair, std::vector< bool > > m_statusPerMpduMap
Map of the current reception status per MPDU that is filled in as long as MPDUs are being processed b...
Definition: phy-entity.h:999
virtual bool CanStartRx(Ptr< const WifiPpdu > ppdu) const
Determine whether the PHY shall issue a PHY-RXSTART.indication primitive in response to a given PPDU.
Definition: phy-entity.cc:1373
virtual void StartTx(Ptr< const WifiPpdu > ppdu)
This function is called by SpectrumWifiPhy to send the PPDU while performing amendment-specific actio...
Definition: phy-entity.cc:1317
virtual uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const
Return the STA ID that has been assigned to the station this PHY belongs to.
Definition: phy-entity.cc:557
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const
Definition: phy-entity.cc:1351
virtual bool IsModeSupported(WifiMode mode) const
Check if the WifiMode is supported.
Definition: phy-entity.cc:100
void ResetReceive(Ptr< Event > event)
Reset PHY at the end of the PPDU under reception after it has failed the PHY header.
Definition: phy-entity.cc:1164
std::list< WifiMode > m_modeList
the list of supported modes
Definition: phy-entity.h:985
Ptr< const Event > GetCurrentEvent() const
Get the pointer to the current event (stored in WifiPhy).
Definition: phy-entity.cc:1197
virtual Ptr< const WifiPsdu > GetAddressedPsduInPpdu(Ptr< const WifiPpdu > ppdu) const
Get the PSDU addressed to that PHY in a PPDU (useful for MU PPDU).
Definition: phy-entity.cc:220
void ErasePreambleEvent(Ptr< const WifiPpdu > ppdu, Time rxDuration)
Erase the event corresponding to the PPDU from the list of preamble events, but consider it as noise ...
Definition: phy-entity.cc:536
void AddPreambleEvent(Ptr< Event > event)
Add an entry to the map of current preamble events (stored in WifiPhy).
Definition: phy-entity.cc:843
virtual void DoEndReceivePayload(Ptr< const WifiPpdu > ppdu)
Perform amendment-specific actions at the end of the reception of the payload.
Definition: phy-entity.cc:774
uint16_t GetCenterFrequencyForChannelWidth(const WifiTxVector &txVector) const
Get the center frequency of the channel corresponding the current TxVector rather than that of the su...
Definition: phy-entity.cc:1302
virtual std::pair< uint16_t, WifiSpectrumBandInfo > GetChannelWidthAndBand(const WifiTxVector &txVector, uint16_t staId) const
Get the channel width and band to use (will be overloaded by child classes).
Definition: phy-entity.cc:830
Ptr< Event > CreateInterferenceEvent(Ptr< const WifiPpdu > ppdu, Time duration, RxPowerWattPerChannelBand &rxPower, bool isStartHePortionRxing=false)
Create an event using WifiPhy's InterferenceHelper class.
Definition: phy-entity.cc:872
@ DROP
drop PPDU and set CCA_BUSY
Definition: phy-entity.h:103
void ScheduleEndOfMpdus(Ptr< Event > event)
Schedule end of MPDUs events.
Definition: phy-entity.cc:595
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:217
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:418
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:351
@ US
microsecond
Definition: nstime.h:118
@ S
second
Definition: nstime.h:116
@ NS
nanosecond
Definition: nstime.h:119
PHY entity for VHT (11ac)
Definition: vht-phy.h:49
static WifiMode GetVhtMcs0()
Return MCS 0 from VHT MCS values.
static WifiCodeRate GetCodeRate(uint8_t mcsValue)
Return the coding rate corresponding to the supplied VHT MCS index.
Definition: vht-phy.cc:406
Time GetDuration(WifiPpduField field, const WifiTxVector &txVector) const override
Get the duration of the PPDU field (or group of fields) used by this entity for the given transmissio...
Definition: vht-phy.cc:176
double GetCcaThreshold(const Ptr< const WifiPpdu > ppdu, WifiChannelListType channelType) const override
Return the CCA threshold in dBm for a given channel type.
Definition: vht-phy.cc:547
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
CcaIndication GetCcaIndication(const Ptr< const WifiPpdu > ppdu) override
Get CCA end time and its corresponding channel list type when a new signal has been received by the P...
Definition: vht-phy.cc:587
static uint64_t CalculateNonHtReferenceRate(WifiCodeRate codeRate, uint16_t constellationSize)
Return the rate (in bps) of the non-HT Reference Rate which corresponds to the supplied code rate and...
Definition: vht-phy.cc:496
static WifiMode GetVhtMcs3()
Return MCS 3 from VHT MCS values.
static WifiMode GetVhtMcs1()
Return MCS 1 from VHT MCS values.
static WifiMode GetVhtMcs4()
Return MCS 4 from VHT MCS values.
static WifiMode GetVhtMcs2()
Return MCS 2 from VHT MCS values.
static uint16_t GetConstellationSize(uint8_t mcsValue)
Return the constellation size corresponding to the supplied VHT MCS index.
Definition: vht-phy.cc:420
WifiMode GetSigMode(WifiPpduField field, const WifiTxVector &txVector) const override
Get the WifiMode for the SIG field specified by the PPDU field.
Definition: vht-phy.cc:138
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:436
static WifiMode CreateWifiMcs(std::string uniqueName, uint8_t mcsValue, WifiModulationClass modClass, bool isMandatory, CodeRateCallback codeRateCallback, ConstellationSizeCallback constellationSizeCallback, PhyRateCallback phyRateCallback, DataRateCallback dataRateCallback, NonHtReferenceRateCallback nonHtReferenceRateCallback, AllowedCallback isAllowedCallback)
Definition: wifi-mode.cc:318
represent a single transmission mode
Definition: wifi-mode.h:51
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
Ptr< WifiMac > GetMac() const
Ptr< HeConfiguration > GetHeConfiguration() const
uint32_t GetSubcarrierSpacing() const
Definition: wifi-phy.cc:2283
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1073
double GetTxGain() const
Return the transmission gain (dB).
Definition: wifi-phy.cc:583
void NotifyRxDrop(Ptr< const WifiPsdu > psdu, WifiPhyRxfailureReason reason)
Public method used to fire a PhyRxDrop trace.
Definition: wifi-phy.cc:1630
uint16_t GetFrequency() const
Definition: wifi-phy.cc:1061
uint8_t GetMaxSupportedRxSpatialStreams() const
Definition: wifi-phy.cc:1341
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1529
virtual WifiSpectrumBandFrequencies ConvertIndicesToFrequencies(const WifiSpectrumBandIndices &indices) const =0
This is a helper function to convert start and stop indices to start and stop frequencies.
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1043
static void AddStaticPhyEntity(WifiModulationClass modulation, Ptr< PhyEntity > phyEntity)
Add the PHY entity to the map of implemented PHY entities for the given modulation class.
Definition: wifi-phy.cc:775
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
Definition: wifi-phy.cc:621
virtual WifiSpectrumBandInfo GetBand(uint16_t bandWidth, uint8_t bandIndex=0)=0
Get the info of a given band.
double GetTxPowerForTransmission(Ptr< const WifiPpdu > ppdu) const
Compute the transmit power for the next transmission.
Definition: wifi-phy.cc:2216
uint64_t GetPreviouslyRxPpduUid() const
Definition: wifi-phy.cc:1869
Time GetLastRxEndTime() const
Return the end time of the last received packet.
Definition: wifi-phy.cc:2131
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1055
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1522
uint8_t GetPrimaryChannelIndex(uint16_t primaryChannelWidth) const
If the operating channel width is a multiple of 20 MHz, return the index of the primary channel of th...
std::set< uint8_t > GetAll20MHzChannelIndicesInPrimary(uint16_t width) const
Get the channel indices of all the 20 MHz channels included in the primary channel of the given width...
static Ptr< SpectrumValue > CreateDuplicated20MhzTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40, const std::vector< bool > &puncturedSubchannels=std::vector< bool >{})
Create a transmit power spectral density corresponding to OFDM duplicated over multiple 20 MHz subcha...
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, const WifiSpectrumBandIndices &ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40, const std::vector< bool > &puncturedSubchannels=std::vector< bool >{})
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE) (802....
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
bool IsTriggerResponding() const
Return true if the Trigger Responding parameter is set to true, false otherwise.
uint16_t GetGuardInterval() const
bool IsSigBCompression() const
Indicate whether the Common field is present in the HE-SIG-B field.
const RuAllocation & GetRuAllocation(uint8_t p20Index) const
Get RU_ALLOCATION field.
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.
WifiPreamble GetPreambleType() const
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
uint16_t GetLength() const
Get the LENGTH field of the L-SIG.
bool IsDlMu() const
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
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.
bool IsUlMu() const
uint16_t GetChannelWidth() const
#define CASE(x)
#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(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:767
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1343
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1355
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Time FemtoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1379
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
WifiPpduField
The type of PPDU field (grouped for convenience)
@ AP
Definition: wifi-mac.h:69
@ OBSS_PD_CCA_RESET
@ WIFI_PREAMBLE_HE_ER_SU
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ 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)
@ WIFI_CHANLIST_PRIMARY
@ WIFI_PPDU_FIELD_SIG_B
SIG-B field.
@ WIFI_PPDU_FIELD_TRAINING
STF + LTF fields (excluding those in preamble for HT-GF)
@ WIFI_PPDU_FIELD_NON_HT_HEADER
PHY header field for DSSS or ERP, short PHY header field for HR/DSSS or ERP, field not present for HT...
@ WIFI_PPDU_FIELD_PREAMBLE
SYNC + SFD fields for DSSS or ERP, shortSYNC + shortSFD fields for HR/DSSS or ERP,...
@ WIFI_PPDU_FIELD_DATA
data field
@ WIFI_PPDU_FIELD_SIG_A
SIG-A field.
#define GET_HE_MCS(x)
Definition: he-phy.cc:1576
Declaration of ns3::HePhy class and ns3::HeSigAParameters struct.
#define HE_PHY
This defines the BSS membership value for HE PHY.
Definition: he-phy.h:48
class anonymous_namespace{he-phy.cc}::ConstructorHe g_constructor_he
the constructor for HE modes
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.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:706
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:40
std::pair< uint32_t, uint32_t > WifiSpectrumBandIndices
typedef for a pair of start and stop sub-band indices
std::map< WifiSpectrumBandInfo, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:77
@ LOG_FUNCTION
Function tracing for non-trivial function calls.
Definition: log.h:106
bool IsDlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a downlink multi-user transmission.
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
bool IsUlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a uplink multi-user transmission.
WifiCodeRate
These constants define the various convolutional coding rates used for the OFDM transmission modes in...
@ WIFI_CODE_RATE_3_4
3/4 coding rate
@ WIFI_CODE_RATE_5_6
5/6 coding rate
STL namespace.
Parameters for received HE-SIG-A for OBSS_PD based SR.
Definition: he-phy.h:54
Status of the reception of the PPDU field.
Definition: phy-entity.h:112
bool isSuccess
outcome (true if success) of the reception
Definition: phy-entity.h:113
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
SignalNoiseDbm structure.
Definition: phy-entity.h:55
WifiSpectrumBandInfo structure containing info about a spectrum band.
WifiSpectrumBandIndices indices
the start and stop indices of the band