A Discrete-Event Network Simulator
API
ht-ppdu.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Orange Labs
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Rediet <getachew.redieteab@orange.com>
18  * Muhammad Iqbal Rochman <muhiqbalcr@uchicago.edu>
19  * Sébastien Deronne <sebastien.deronne@gmail.com> (HtSigHeader)
20  */
21 
22 #include "ht-ppdu.h"
23 
24 #include "ht-phy.h"
25 
26 #include "ns3/log.h"
27 #include "ns3/wifi-phy.h"
28 #include "ns3/wifi-psdu.h"
29 #include "ns3/wifi-utils.h"
30 
31 namespace ns3
32 {
33 
34 NS_LOG_COMPONENT_DEFINE("HtPpdu");
35 
37  const WifiTxVector& txVector,
38  uint16_t txCenterFreq,
39  Time ppduDuration,
40  WifiPhyBand band,
41  uint64_t uid)
42  : OfdmPpdu(psdu,
43  txVector,
44  txCenterFreq,
45  band,
46  uid,
47  false) // don't instantiate LSigHeader of OfdmPpdu
48 {
49  NS_LOG_FUNCTION(this << psdu << txVector << txCenterFreq << ppduDuration << band << uid);
50  SetPhyHeaders(txVector, ppduDuration, psdu->GetSize());
51 }
52 
53 void
54 HtPpdu::SetPhyHeaders(const WifiTxVector& txVector, Time ppduDuration, std::size_t psduSize)
55 {
56  NS_LOG_FUNCTION(this << txVector << ppduDuration << psduSize);
57 
58 #ifdef NS3_BUILD_PROFILE_DEBUG
59  LSigHeader lSig;
60  SetLSigHeader(lSig, ppduDuration);
61 
62  HtSigHeader htSig;
63  SetHtSigHeader(htSig, txVector, psduSize);
64 
65  m_phyHeaders->AddHeader(htSig);
66  m_phyHeaders->AddHeader(lSig);
67 #else
68  SetLSigHeader(m_lSig, ppduDuration);
69  SetHtSigHeader(m_htSig, txVector, psduSize);
70 #endif
71 }
72 
73 void
74 HtPpdu::SetLSigHeader(LSigHeader& lSig, Time ppduDuration) const
75 {
76  uint8_t sigExtension = 0;
78  {
79  sigExtension = 6;
80  }
81  uint16_t length = ((ceil((static_cast<double>(ppduDuration.GetNanoSeconds() - (20 * 1000) -
82  (sigExtension * 1000)) /
83  1000) /
84  4.0) *
85  3) -
86  3);
87  lSig.SetLength(length);
88 }
89 
90 void
91 HtPpdu::SetHtSigHeader(HtSigHeader& htSig, const WifiTxVector& txVector, std::size_t psduSize) const
92 {
93  htSig.SetMcs(txVector.GetMode().GetMcsValue());
94  htSig.SetChannelWidth(txVector.GetChannelWidth());
95  htSig.SetHtLength(psduSize);
96  htSig.SetAggregation(txVector.IsAggregation());
97  htSig.SetShortGuardInterval(txVector.GetGuardInterval() == 400);
98 }
99 
102 {
103  WifiTxVector txVector;
104  txVector.SetPreambleType(m_preamble);
105 
106 #ifdef NS3_BUILD_PROFILE_DEBUG
107  auto phyHeaders = m_phyHeaders->Copy();
108 
109  LSigHeader lSig;
110  if (phyHeaders->RemoveHeader(lSig) == 0)
111  {
112  NS_FATAL_ERROR("Missing L-SIG header in HT PPDU");
113  }
114 
115  HtSigHeader htSig;
116  if (phyHeaders->RemoveHeader(htSig) == 0)
117  {
118  NS_FATAL_ERROR("Missing HT-SIG header in HT PPDU");
119  }
120 
121  SetTxVectorFromPhyHeaders(txVector, lSig, htSig);
122 #else
123  SetTxVectorFromPhyHeaders(txVector, m_lSig, m_htSig);
124 #endif
125 
126  return txVector;
127 }
128 
129 void
131  const LSigHeader& lSig,
132  const HtSigHeader& htSig) const
133 {
134  txVector.SetMode(HtPhy::GetHtMcs(htSig.GetMcs()));
135  txVector.SetChannelWidth(htSig.GetChannelWidth());
136  txVector.SetNss(1 + (htSig.GetMcs() / 8));
137  txVector.SetGuardInterval(htSig.GetShortGuardInterval() ? 400 : 800);
138  txVector.SetAggregation(htSig.GetAggregation());
139 }
140 
141 Time
143 {
144  Time ppduDuration = Seconds(0);
145  const WifiTxVector& txVector = GetTxVector();
146 
147  uint16_t htLength = 0;
148 #ifdef NS3_BUILD_PROFILE_DEBUG
149  auto phyHeaders = m_phyHeaders->Copy();
150 
151  LSigHeader lSig;
152  phyHeaders->RemoveHeader(lSig);
153  HtSigHeader htSig;
154  phyHeaders->RemoveHeader(htSig);
155 
156  htLength = htSig.GetHtLength();
157 #else
158  htLength = m_htSig.GetHtLength();
159 #endif
160 
161  ppduDuration = WifiPhy::CalculateTxDuration(htLength, txVector, m_band);
162  return ppduDuration;
163 }
164 
167 {
168  return Ptr<WifiPpdu>(new HtPpdu(*this), false);
169 }
170 
172  : m_mcs(0),
173  m_cbw20_40(0),
174  m_htLength(0),
175  m_aggregation(0),
176  m_sgi(0)
177 {
178 }
179 
180 TypeId
182 {
183  static TypeId tid = TypeId("ns3::HtSigHeader")
184  .SetParent<Header>()
185  .SetGroupName("Wifi")
186  .AddConstructor<HtSigHeader>();
187  return tid;
188 }
189 
190 TypeId
192 {
193  return GetTypeId();
194 }
195 
196 void
197 HtPpdu::HtSigHeader::Print(std::ostream& os) const
198 {
199  os << "MCS=" << +m_mcs << " HT_LENGTH=" << m_htLength << " CHANNEL_WIDTH=" << GetChannelWidth()
200  << " SGI=" << +m_sgi << " AGGREGATION=" << +m_aggregation;
201 }
202 
203 uint32_t
205 {
206  return 6;
207 }
208 
209 void
211 {
212  NS_ASSERT(mcs <= 31);
213  m_mcs = mcs;
214 }
215 
216 uint8_t
218 {
219  return m_mcs;
220 }
221 
222 void
224 {
225  m_cbw20_40 = (channelWidth > 20) ? 1 : 0;
226 }
227 
228 uint16_t
230 {
231  return m_cbw20_40 ? 40 : 20;
232 }
233 
234 void
236 {
237  m_htLength = length;
238 }
239 
240 uint16_t
242 {
243  return m_htLength;
244 }
245 
246 void
248 {
249  m_aggregation = aggregation ? 1 : 0;
250 }
251 
252 bool
254 {
255  return m_aggregation;
256 }
257 
258 void
260 {
261  m_sgi = sgi ? 1 : 0;
262 }
263 
264 bool
266 {
267  return m_sgi;
268 }
269 
270 void
272 {
273  uint8_t byte = m_mcs;
274  byte |= ((m_cbw20_40 & 0x01) << 7);
275  start.WriteU8(byte);
276  start.WriteU16(m_htLength);
277  byte = (0x01 << 2); // Set Reserved bit #2 to 1
278  byte |= ((m_aggregation & 0x01) << 3);
279  byte |= ((m_sgi & 0x01) << 7);
280  start.WriteU8(byte);
281  start.WriteU16(0);
282 }
283 
284 uint32_t
286 {
288  uint8_t byte = i.ReadU8();
289  m_mcs = byte & 0x7f;
290  m_cbw20_40 = ((byte >> 7) & 0x01);
291  m_htLength = i.ReadU16();
292  byte = i.ReadU8();
293  m_aggregation = ((byte >> 3) & 0x01);
294  m_sgi = ((byte >> 7) & 0x01);
295  i.ReadU16();
296  return i.GetDistanceFrom(start);
297 }
298 
299 } // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint8_t ReadU8()
Definition: buffer.h:1027
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:783
uint16_t ReadU16()
Definition: buffer.h:1035
Protocol header serialization and deserialization.
Definition: header.h:44
virtual uint32_t Deserialize(Buffer::Iterator start)=0
Deserialize the object from a buffer iterator.
static WifiMode GetHtMcs(uint8_t index)
Return the HT MCS corresponding to the provided index.
Definition: ht-phy.cc:490
HT PHY header (HT-SIG1/2).
Definition: ht-ppdu.h:52
void Print(std::ostream &os) const override
Definition: ht-ppdu.cc:197
uint16_t GetHtLength() const
Return the HT length field of HT-SIG (in bytes).
Definition: ht-ppdu.cc:241
uint8_t GetMcs() const
Return the MCS field of HT-SIG.
Definition: ht-ppdu.cc:217
void SetHtLength(uint16_t length)
Fill the HT length field of HT-SIG (in bytes).
Definition: ht-ppdu.cc:235
bool GetAggregation() const
Return the aggregation field of HT-SIG.
Definition: ht-ppdu.cc:253
void SetMcs(uint8_t mcs)
Fill the MCS field of HT-SIG.
Definition: ht-ppdu.cc:210
bool GetShortGuardInterval() const
Return the short guard interval field of HT-SIG.
Definition: ht-ppdu.cc:265
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: ht-ppdu.cc:191
uint16_t GetChannelWidth() const
Return the channel width (in MHz).
Definition: ht-ppdu.cc:229
void SetAggregation(bool aggregation)
Fill the aggregation field of HT-SIG.
Definition: ht-ppdu.cc:247
uint32_t GetSerializedSize() const override
Definition: ht-ppdu.cc:204
void SetChannelWidth(uint16_t channelWidth)
Fill the channel width field of HT-SIG (in MHz).
Definition: ht-ppdu.cc:223
void SetShortGuardInterval(bool sgi)
Fill the short guard interval field of HT-SIG.
Definition: ht-ppdu.cc:259
static TypeId GetTypeId()
Get the type ID.
Definition: ht-ppdu.cc:181
void Serialize(Buffer::Iterator start) const override
Definition: ht-ppdu.cc:271
WifiTxVector DoGetTxVector() const override
Get the TXVECTOR used to send the PPDU.
Definition: ht-ppdu.cc:101
Ptr< WifiPpdu > Copy() const override
Copy this instance.
Definition: ht-ppdu.cc:166
void SetHtSigHeader(HtSigHeader &htSig, const WifiTxVector &txVector, std::size_t psduSize) const
Fill in the HT-SIG header.
Definition: ht-ppdu.cc:91
virtual void SetLSigHeader(LSigHeader &lSig, Time ppduDuration) const
Fill in the L-SIG header.
Definition: ht-ppdu.cc:74
void SetPhyHeaders(const WifiTxVector &txVector, Time ppduDuration, std::size_t psduSize)
Fill in the PHY headers.
Definition: ht-ppdu.cc:54
void SetTxVectorFromPhyHeaders(WifiTxVector &txVector, const LSigHeader &lSig, const HtSigHeader &htSig) const
Fill in the TXVECTOR from PHY headers.
Definition: ht-ppdu.cc:130
Time GetTxDuration() const override
Get the total transmission duration of the PPDU.
Definition: ht-ppdu.cc:142
HtPpdu(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint16_t txCenterFreq, Time ppduDuration, WifiPhyBand band, uint64_t uid)
Create an HT PPDU.
Definition: ht-ppdu.cc:36
OFDM and ERP OFDM L-SIG PHY header.
Definition: ofdm-ppdu.h:55
void SetLength(uint16_t length)
Fill the LENGTH field of L-SIG (in bytes).
Definition: ofdm-ppdu.cc:257
OFDM PPDU (11a)
Definition: ofdm-ppdu.h:48
WifiPhyBand m_band
the WifiPhyBand used to transmit that PPDU
Definition: ofdm-ppdu.h:125
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:417
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1480
WifiPreamble m_preamble
the PHY preamble
Definition: wifi-ppdu.h:201
const WifiTxVector & GetTxVector() const
Get the TXVECTOR used to send the PPDU.
Definition: wifi-ppdu.cc:82
Ptr< Packet > m_phyHeaders
the PHY headers contained in this PPDU
Definition: wifi-ppdu.h:211
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:273
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint16_t GetGuardInterval() const
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
bool IsAggregation() const
Checks whether the PSDU contains A-MPDU.
uint16_t GetChannelWidth() const
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
Declaration of ns3::HtPhy class.
Declaration of ns3::HtPpdu class.
Every class exported by the ns3 library is enclosed in the ns3 namespace.