A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-ppdu.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 Orange Labs
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Rediet <getachew.redieteab@orange.com>
7 */
8
9#include "wifi-ppdu.h"
10
12#include "wifi-psdu.h"
13
14#include "ns3/log.h"
15
16namespace
17{
18/**
19 * Get the center frequency of each segment covered by the provided channel width. If the specified
20 * channel width is contained in a single frequency segment, a single center frequency is returned.
21 * If the specified channel width is spread over multiple frequency segments (e.g. 160 MHz if
22 * operating channel is 80+80MHz), multiple center frequencies are returned.
23 *
24 * \param channel the operating channel of the PHY
25 * \param channelWidth the channel width
26 * \return the center frequency of each segment covered by the given width
27 */
28std::vector<ns3::MHz_u>
30 ns3::MHz_u channelWidth)
31{
32 if (!channel.IsSet())
33 {
34 return {};
35 }
36 std::vector<ns3::MHz_u> freqs{};
37 const auto width = std::min(channelWidth, channel.GetWidth(0));
38 const auto primarySegmentIndex = channel.GetPrimarySegmentIndex(width);
39 const auto secondarySegmentIndex = channel.GetSecondarySegmentIndex(width);
40 const auto primaryIndex = channel.GetPrimaryChannelIndex(channelWidth);
41 const auto segmentIndices =
42 ((channel.GetNSegments() < 2) || (channelWidth <= channel.GetWidth(primarySegmentIndex)))
43 ? std::vector<uint8_t>{primarySegmentIndex}
44 : std::vector<uint8_t>{primarySegmentIndex, secondarySegmentIndex};
45 for (auto segmentIndex : segmentIndices)
46 {
47 const auto segmentFrequency = channel.GetFrequency(segmentIndex);
48 const auto segmentWidth = channel.GetWidth(segmentIndex);
49 // segmentOffset has to be an (unsigned) integer to ensure correct calculation
50 const uint8_t segmentOffset = (primarySegmentIndex * (segmentWidth / channelWidth));
51 const auto freq =
52 segmentFrequency - (segmentWidth / 2.) + (primaryIndex - segmentOffset + 0.5) * width;
53 freqs.push_back(freq);
54 }
55 return freqs;
56}
57} // namespace
58
59namespace ns3
60{
61
62NS_LOG_COMPONENT_DEFINE("WifiPpdu");
63
65 const WifiTxVector& txVector,
66 const WifiPhyOperatingChannel& channel,
67 uint64_t uid /* = UINT64_MAX */)
68 : m_preamble(txVector.GetPreambleType()),
69 m_modulation(txVector.IsValid() ? txVector.GetModulationClass() : WIFI_MOD_CLASS_UNKNOWN),
70 m_txCenterFreqs(GetChannelCenterFrequenciesPerSegment(channel, txVector.GetChannelWidth())),
71 m_uid(uid),
72 m_txVector(txVector),
73 m_operatingChannel(channel),
74 m_truncatedTx(false),
75 m_txPowerLevel(txVector.GetTxPowerLevel()),
76 m_txAntennas(txVector.GetNTx()),
77 m_txChannelWidth(txVector.GetChannelWidth())
78{
79 NS_LOG_FUNCTION(this << *psdu << txVector << channel << uid);
80 m_psdus.insert(std::make_pair(SU_STA_ID, psdu));
81}
82
84 const WifiTxVector& txVector,
85 const WifiPhyOperatingChannel& channel,
86 uint64_t uid)
87 : m_preamble(txVector.GetPreambleType()),
88 m_modulation(txVector.IsValid() ? txVector.GetMode(psdus.begin()->first).GetModulationClass()
90 m_txCenterFreqs(GetChannelCenterFrequenciesPerSegment(channel, txVector.GetChannelWidth())),
91 m_uid(uid),
92 m_txVector(txVector),
93 m_operatingChannel(channel),
94 m_truncatedTx(false),
95 m_txPowerLevel(txVector.GetTxPowerLevel()),
96 m_txAntennas(txVector.GetNTx()),
97 m_txChannelWidth(txVector.GetChannelWidth())
98{
99 NS_LOG_FUNCTION(this << psdus << txVector << channel << uid);
100 m_psdus = psdus;
101}
102
103const WifiTxVector&
105{
106 if (!m_txVector.has_value())
107 {
109 m_txVector->SetTxPowerLevel(m_txPowerLevel);
110 m_txVector->SetNTx(m_txAntennas);
111 m_txVector->SetChannelWidth(m_txChannelWidth);
112 }
113 return m_txVector.value();
114}
115
118{
119 NS_FATAL_ERROR("This method should not be called for the base WifiPpdu class. Use the "
120 "overloaded version in the amendment-specific PPDU subclasses instead!");
121 return WifiTxVector(); // should be overloaded
122}
123
124void
126{
127 NS_LOG_FUNCTION(this);
128 m_txVector.reset();
129}
130
131void
132WifiPpdu::UpdateTxVector(const WifiTxVector& updatedTxVector) const
133{
134 NS_LOG_FUNCTION(this << updatedTxVector);
136 m_txVector = updatedTxVector;
137}
138
141{
142 return m_psdus.begin()->second;
143}
144
145bool
147{
148 return m_truncatedTx;
149}
150
151void
153{
154 NS_LOG_FUNCTION(this);
155 m_truncatedTx = true;
156}
157
160{
161 return m_modulation;
162}
163
164MHz_u
166{
167 return m_txChannelWidth;
168}
169
170std::vector<MHz_u>
172{
173 return m_txCenterFreqs;
174}
175
176bool
178{
179 NS_LOG_FUNCTION(this << minFreq << maxFreq);
180 // all segments have the same width
181 const MHz_u txChannelWidth = (m_txChannelWidth / m_txCenterFreqs.size());
182 for (auto txCenterFreq : m_txCenterFreqs)
183 {
184 const auto minTxFreq = txCenterFreq - txChannelWidth / 2;
185 const auto maxTxFreq = txCenterFreq + txChannelWidth / 2;
186 /**
187 * The PPDU does not overlap the channel in two cases.
188 *
189 * First non-overlapping case:
190 *
191 * ┌─────────┐
192 * PPDU │ Nominal │
193 * │ Band │
194 * └─────────┘
195 * minTxFreq maxTxFreq
196 *
197 * minFreq maxFreq
198 * ┌──────────────────────────────┐
199 * │ Channel │
200 * └──────────────────────────────┘
201 *
202 * Second non-overlapping case:
203 *
204 * ┌─────────┐
205 * PPDU │ Nominal │
206 * │ Band │
207 * └─────────┘
208 * minTxFreq maxTxFreq
209 *
210 * minFreq maxFreq
211 * ┌──────────────────────────────┐
212 * │ Channel │
213 * └──────────────────────────────┘
214 */
215 if ((minTxFreq < maxFreq) && (maxTxFreq > minFreq))
216 {
217 return true;
218 }
219 }
220 return false;
221}
222
223uint64_t
225{
226 return m_uid;
227}
228
231{
232 return m_preamble;
233}
234
237{
238 return WIFI_PPDU_TYPE_SU;
239}
240
241uint16_t
243{
244 return SU_STA_ID;
245}
246
247Time
249{
250 NS_FATAL_ERROR("This method should not be called for the base WifiPpdu class. Use the "
251 "overloaded version in the amendment-specific PPDU subclasses instead!");
252 return MicroSeconds(0); // should be overloaded
253}
254
255void
256WifiPpdu::Print(std::ostream& os) const
257{
258 os << "[ preamble=" << m_preamble << ", modulation=" << m_modulation
259 << ", truncatedTx=" << (m_truncatedTx ? "Y" : "N") << ", UID=" << m_uid << ", "
260 << PrintPayload() << "]";
261}
262
263std::string
265{
266 std::ostringstream ss;
267 ss << "PSDU=" << GetPsdu() << " ";
268 return ss.str();
269}
270
273{
274 NS_FATAL_ERROR("This method should not be called for the base WifiPpdu class. Use the "
275 "overloaded version in the amendment-specific PPDU subclasses instead!");
276 return Ptr<WifiPpdu>(new WifiPpdu(*this), false);
277}
278
279std::ostream&
280operator<<(std::ostream& os, const Ptr<const WifiPpdu>& ppdu)
281{
282 ppdu->Print(os);
283 return os;
284}
285
286std::ostream&
287operator<<(std::ostream& os, const WifiConstPsduMap& psdus)
288{
289 for (const auto& psdu : psdus)
290 {
291 os << "PSDU for STA_ID=" << psdu.first << " (" << *psdu.second << ") ";
292 }
293 return os;
294}
295
296} // namespace ns3
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
Class that keeps track of all information about the current PHY operating channel.
void Print(std::ostream &os) const
Print the PPDU contents.
Definition wifi-ppdu.cc:256
virtual Time GetTxDuration() const
Get the total transmission duration of the PPDU.
Definition wifi-ppdu.cc:248
bool IsTruncatedTx() const
Definition wifi-ppdu.cc:146
WifiPreamble GetPreamble() const
Get the preamble of the PPDU.
Definition wifi-ppdu.cc:230
virtual MHz_u GetTxChannelWidth() const
Get the channel width over which the PPDU will effectively be transmitted.
Definition wifi-ppdu.cc:165
void ResetTxVector() const
Reset the TXVECTOR.
Definition wifi-ppdu.cc:125
virtual uint16_t GetStaId() const
Get the ID of the STA that transmitted the PPDU for UL MU, SU_STA_ID otherwise.
Definition wifi-ppdu.cc:242
WifiPpdu(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, const WifiPhyOperatingChannel &channel, uint64_t uid=UINT64_MAX)
Create a PPDU storing a PSDU.
Definition wifi-ppdu.cc:64
void UpdateTxVector(const WifiTxVector &updatedTxVector) const
Update the TXVECTOR based on some information known at the receiver.
Definition wifi-ppdu.cc:132
virtual WifiPpduType GetType() const
Return the PPDU type (.
Definition wifi-ppdu.cc:236
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:199
WifiModulationClass m_modulation
the modulation used for the transmission of this PPDU
Definition wifi-ppdu.h:193
WifiPreamble m_preamble
the PHY preamble
Definition wifi-ppdu.h:192
MHz_u m_txChannelWidth
The channel width used for the transmission of this PPDU.
Definition wifi-ppdu.h:217
Ptr< const WifiPsdu > GetPsdu() const
Get the payload of the PPDU.
Definition wifi-ppdu.cc:140
virtual WifiTxVector DoGetTxVector() const
Get the TXVECTOR used to send the PPDU.
Definition wifi-ppdu.cc:117
uint64_t m_uid
the unique ID of this PPDU
Definition wifi-ppdu.h:197
std::vector< MHz_u > m_txCenterFreqs
the center frequency per segment used for the transmission of this PPDU
Definition wifi-ppdu.h:195
void SetTruncatedTx()
Indicate that the PPDU's transmission was aborted due to transmitter switch off.
Definition wifi-ppdu.cc:152
bool DoesOverlapChannel(MHz_u minFreq, MHz_u maxFreq) const
Check whether the given PPDU overlaps a given channel.
Definition wifi-ppdu.cc:177
const WifiTxVector & GetTxVector() const
Get the TXVECTOR used to send the PPDU.
Definition wifi-ppdu.cc:104
uint64_t GetUid() const
Get the UID of the PPDU.
Definition wifi-ppdu.cc:224
WifiModulationClass GetModulation() const
Get the modulation used for the PPDU.
Definition wifi-ppdu.cc:159
WifiConstPsduMap m_psdus
the PSDUs contained in this PPDU
Definition wifi-ppdu.h:194
virtual std::string PrintPayload() const
Print the payload of the PPDU.
Definition wifi-ppdu.cc:264
uint8_t m_txAntennas
the number of antennas used to transmit this PPDU
Definition wifi-ppdu.h:215
uint8_t m_txPowerLevel
the transmission power level (used only for TX and initializing the returned WifiTxVector)
Definition wifi-ppdu.h:213
virtual Ptr< WifiPpdu > Copy() const
Copy this instance.
Definition wifi-ppdu.cc:272
bool m_truncatedTx
flag indicating whether the frame's transmission was aborted due to transmitter switch off
Definition wifi-ppdu.h:211
std::vector< MHz_u > GetTxCenterFreqs() const
Definition wifi-ppdu.cc:171
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1332
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiPpduType
The type of PPDU (SU, DL MU, or UL MU)
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
@ WIFI_PPDU_TYPE_SU
@ WIFI_MOD_CLASS_UNKNOWN
Modulation class unknown or unspecified.
std::vector< ns3::MHz_u > GetChannelCenterFrequenciesPerSegment(const ns3::WifiPhyOperatingChannel &channel, ns3::MHz_u channelWidth)
Get the center frequency of each segment covered by the provided channel width.
Definition wifi-ppdu.cc:29
Definition first.py:1
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.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
double MHz_u
MHz weak type.
Definition wifi-units.h:31
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
Declaration of ns3::WifiPpdu class and ns3::WifiConstPsduMap.