A Discrete-Event Network Simulator
API
interference-helper.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  * S├ębastien Deronne <sebastien.deronne@gmail.com>
20  */
21 
22 #include "ns3/simulator.h"
23 #include "ns3/log.h"
24 #include "ns3/packet.h"
25 #include "interference-helper.h"
26 #include "wifi-phy.h"
27 #include "error-rate-model.h"
28 #include "wifi-utils.h"
29 #include "wifi-ppdu.h"
30 #include "wifi-psdu.h"
31 
32 namespace ns3 {
33 
34 NS_LOG_COMPONENT_DEFINE ("InterferenceHelper");
35 
36 /****************************************************************
37  * PHY event class
38  ****************************************************************/
39 
40 Event::Event (Ptr<const WifiPpdu> ppdu, WifiTxVector txVector, Time duration, double rxPower)
41  : m_ppdu (ppdu),
42  m_txVector (txVector),
43  m_startTime (Simulator::Now ()),
44  m_endTime (m_startTime + duration),
45  m_rxPowerW (rxPower)
46 {
47 }
48 
50 {
51 }
52 
54 Event::GetPsdu (void) const
55 {
56  return m_ppdu->GetPsdu ();
57 }
58 
60 Event::GetPpdu (void) const
61 {
62  return m_ppdu;
63 }
64 
65 Time
66 Event::GetStartTime (void) const
67 {
68  return m_startTime;
69 }
70 
71 Time
72 Event::GetEndTime (void) const
73 {
74  return m_endTime;
75 }
76 
77 Time
78 Event::GetDuration (void) const
79 {
80  return m_endTime - m_startTime;
81 }
82 
83 double
84 Event::GetRxPowerW (void) const
85 {
86  return m_rxPowerW;
87 }
88 
90 Event::GetTxVector (void) const
91 {
92  return m_txVector;
93 }
94 
95 std::ostream & operator << (std::ostream &os, const Event &event)
96 {
97  os << "start=" << event.GetStartTime () << ", end=" << event.GetEndTime ()
98  << ", TXVECTOR=" << event.GetTxVector ()
99  << ", power=" << event.GetRxPowerW () << "W"
100  << ", PPDU=" << event.GetPpdu ();
101  return os;
102 }
103 
104 /****************************************************************
105  * Class which records SNIR change events for a
106  * short period of time.
107  ****************************************************************/
108 
110  : m_power (power),
111  m_event (event)
112 {
113 }
114 
115 double
117 {
118  return m_power;
119 }
120 
121 void
123 {
124  m_power += power;
125 }
126 
129 {
130  return m_event;
131 }
132 
133 
134 /****************************************************************
135  * The actual InterferenceHelper
136  ****************************************************************/
137 
139  : m_errorRateModel (0),
140  m_numRxAntennas (1),
141  m_firstPower (0),
142  m_rxing (false)
143 {
144  // Always have a zero power noise event in the list
145  AddNiChangeEvent (Time (0), NiChange (0.0, 0));
146 }
147 
149 {
150  EraseEvents ();
151  m_errorRateModel = 0;
152 }
153 
155 InterferenceHelper::Add (Ptr<const WifiPpdu> ppdu, WifiTxVector txVector, Time duration, double rxPowerW)
156 {
157  Ptr<Event> event = Create<Event> (ppdu, txVector, duration, rxPowerW);
158  AppendEvent (event);
159  return event;
160 }
161 
162 void
163 InterferenceHelper::AddForeignSignal (Time duration, double rxPowerW)
164 {
165  // Parameters other than duration and rxPowerW are unused for this type
166  // of signal, so we provide dummy versions
167  WifiMacHeader hdr;
169  Ptr<WifiPpdu> fakePpdu = Create<WifiPpdu> (Create<WifiPsdu> (Create<Packet> (0), hdr),
170  WifiTxVector (), duration, 0);
171  Add (fakePpdu, WifiTxVector (), duration, rxPowerW);
172 }
173 
174 void
176 {
177  m_noiseFigure = value;
178 }
179 
180 void
182 {
183  m_errorRateModel = rate;
184 }
185 
188 {
189  return m_errorRateModel;
190 }
191 
192 void
194 {
195  m_numRxAntennas = rx;
196 }
197 
198 Time
200 {
201  Time now = Simulator::Now ();
202  auto i = GetPreviousPosition (now);
203  Time end = i->first;
204  for (; i != m_niChanges.end (); ++i)
205  {
206  double noiseInterferenceW = i->second.GetPower ();
207  end = i->first;
208  if (noiseInterferenceW < energyW)
209  {
210  break;
211  }
212  }
213  return end > now ? end - now : MicroSeconds (0);
214 }
215 
216 void
218 {
219  NS_LOG_FUNCTION (this);
220  double previousPowerStart = 0;
221  double previousPowerEnd = 0;
222  previousPowerStart = GetPreviousPosition (event->GetStartTime ())->second.GetPower ();
223  previousPowerEnd = GetPreviousPosition (event->GetEndTime ())->second.GetPower ();
224 
225  if (!m_rxing)
226  {
227  m_firstPower = previousPowerStart;
228  // Always leave the first zero power noise event in the list
229  m_niChanges.erase (++(m_niChanges.begin ()),
230  GetNextPosition (event->GetStartTime ()));
231  }
232  auto first = AddNiChangeEvent (event->GetStartTime (), NiChange (previousPowerStart, event));
233  auto last = AddNiChangeEvent (event->GetEndTime (), NiChange (previousPowerEnd, event));
234  for (auto i = first; i != last; ++i)
235  {
236  i->second.AddPower (event->GetRxPowerW ());
237  }
238 }
239 
240 double
241 InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint16_t channelWidth) const
242 {
243  //thermal noise at 290K in J/s = W
244  static const double BOLTZMANN = 1.3803e-23;
245  //Nt is the power of thermal noise in W
246  double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
247  //receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
248  double noiseFloor = m_noiseFigure * Nt;
249  double noise = noiseFloor + noiseInterference;
250  double snr = signal / noise; //linear scale
251  NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr=" << RatioToDb(snr) << "dB");
252  return snr;
253 }
254 
255 double
257 {
258  double noiseInterferenceW = m_firstPower;
259  auto it = m_niChanges.find (event->GetStartTime ());
260  for (; it != m_niChanges.end () && it->first < Simulator::Now (); ++it)
261  {
262  noiseInterferenceW = it->second.GetPower () - event->GetRxPowerW ();
263  }
264  it = m_niChanges.find (event->GetStartTime ());
265  for (; it != m_niChanges.end () && it->second.GetEvent () != event; ++it);
266  ni->emplace (event->GetStartTime (), NiChange (0, event));
267  while (++it != m_niChanges.end () && it->second.GetEvent () != event)
268  {
269  ni->insert (*it);
270  }
271  ni->emplace (event->GetEndTime (), NiChange (0, event));
272  NS_ASSERT_MSG (noiseInterferenceW >= 0, "CalculateNoiseInterferenceW returns negative value " << noiseInterferenceW);
273  return noiseInterferenceW;
274 }
275 
276 double
277 InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, WifiTxVector txVector) const
278 {
279  if (duration.IsZero ())
280  {
281  return 1.0;
282  }
283  uint64_t rate = mode.GetDataRate (txVector.GetChannelWidth ());
284  uint64_t nbits = static_cast<uint64_t> (rate * duration.GetSeconds ());
285  double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits);
286  return csr;
287 }
288 
289 double
291 {
292  if (duration.IsZero ())
293  {
294  return 1.0;
295  }
296  WifiMode mode = txVector.GetMode ();
297  uint64_t rate = mode.GetDataRate (txVector);
298  uint64_t nbits = static_cast<uint64_t> (rate * duration.GetSeconds ());
299  if (txVector.GetMode ().GetModulationClass () >= WIFI_MOD_CLASS_HT)
300  {
301  nbits /= txVector.GetNss (); //divide effective number of bits by NSS to achieve same chunk error rate as SISO for AWGN
302  double gain = (txVector.GetNTx () * m_numRxAntennas); //compute gain offered by MIMO, SIMO or MISO compared to SISO for AWGN
303  NS_LOG_DEBUG ("TX=" << +txVector.GetNTx () <<
304  ", RX=" << +m_numRxAntennas <<
305  ", SNIR improvement=+" << 10 * std::log10 (gain) << "dB");
306  snir *= gain;
307  }
308  double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits);
309  return csr;
310 }
311 
312 double
314 {
315  NS_LOG_FUNCTION (this << window.first << window.second);
316  const WifiTxVector txVector = event->GetTxVector ();
317  double psr = 1.0; /* Packet Success Rate */
318  auto j = ni->begin ();
319  Time previous = j->first;
320  WifiMode payloadMode = event->GetTxVector ().GetMode ();
321  WifiPreamble preamble = txVector.GetPreambleType ();
322  Time phyHeaderStart = j->first + WifiPhy::GetPhyPreambleDuration (txVector); //PPDU start time + preamble
323  Time phyLSigHeaderEnd = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG
324  Time phyTrainingSymbolsStart = phyLSigHeaderEnd + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A
325  Time phyPayloadStart = phyTrainingSymbolsStart + WifiPhy::GetPhyTrainingSymbolDuration (txVector) + WifiPhy::GetPhySigBDuration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
326  Time windowStart = phyPayloadStart + window.first;
327  Time windowEnd = phyPayloadStart + window.second;
328  double noiseInterferenceW = m_firstPower;
329  double powerW = event->GetRxPowerW ();
330  while (++j != ni->end ())
331  {
332  Time current = j->first;
333  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
334  NS_ASSERT (current >= previous);
335  double snr = CalculateSnr (powerW, noiseInterferenceW, txVector.GetChannelWidth ());
336  //Case 1: Both previous and current point to the windowed payload
337  if (previous >= windowStart)
338  {
339  psr *= CalculatePayloadChunkSuccessRate (snr, Min (windowEnd, current) - previous, txVector);
340  NS_LOG_DEBUG ("Both previous and current point to the windowed payload: mode=" << payloadMode << ", psr=" << psr);
341  }
342  //Case 2: previous is before windowed payload and current is in the windowed payload
343  else if (current >= windowStart)
344  {
345  psr *= CalculatePayloadChunkSuccessRate (snr, Min (windowEnd, current) - windowStart, txVector);
346  NS_LOG_DEBUG ("previous is before windowed payload and current is in the windowed payload: mode=" << payloadMode << ", psr=" << psr);
347  }
348  noiseInterferenceW = j->second.GetPower () - powerW;
349  previous = j->first;
350  if (previous > windowEnd)
351  {
352  NS_LOG_DEBUG ("Stop: new previous=" << previous << " after time window end=" << windowEnd);
353  break;
354  }
355  }
356  double per = 1 - psr;
357  return per;
358 }
359 
360 double
362 {
363  NS_LOG_FUNCTION (this);
364  const WifiTxVector txVector = event->GetTxVector ();
365  double psr = 1.0; /* Packet Success Rate */
366  auto j = ni->begin ();
367  Time previous = j->first;
368  WifiPreamble preamble = txVector.GetPreambleType ();
369  WifiMode headerMode = WifiPhy::GetPhyHeaderMode (txVector);
370  Time phyHeaderStart = j->first + WifiPhy::GetPhyPreambleDuration (txVector); //PPDU start time + preamble
371  Time phyLSigHeaderEnd = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG
372  Time phyTrainingSymbolsStart = phyLSigHeaderEnd + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A
373  Time phyPayloadStart = phyTrainingSymbolsStart + WifiPhy::GetPhyTrainingSymbolDuration (txVector) + WifiPhy::GetPhySigBDuration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
374  double noiseInterferenceW = m_firstPower;
375  double powerW = event->GetRxPowerW ();
376  while (++j != ni->end ())
377  {
378  Time current = j->first;
379  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
380  NS_ASSERT (current >= previous);
381  double snr = CalculateSnr (powerW, noiseInterferenceW, txVector.GetChannelWidth ());
382  //Case 1: previous and current after payload start
383  if (previous >= phyPayloadStart)
384  {
385  psr *= 1;
386  NS_LOG_DEBUG ("Case 1 - previous and current after payload start: nothing to do");
387  }
388  //Case 2: previous is in training or in SIG-B: non-HT will not enter here since it didn't enter in the last two and they are all the same for non-HT
389  else if (previous >= phyTrainingSymbolsStart)
390  {
391  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
392  psr *= 1;
393  NS_LOG_DEBUG ("Case 2 - previous is in training or in SIG-B: nothing to do");
394  }
395  //Case 3: previous is in HT-SIG or SIG-A: non-HT will not enter here since it didn't enter in the last two and they are all the same for non-HT
396  else if (previous >= phyLSigHeaderEnd)
397  {
398  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
399  psr *= 1;
400  NS_LOG_DEBUG ("Case 3cii - previous is in HT-SIG or SIG-A: nothing to do");
401  }
402  //Case 4: previous in L-SIG: HT GF will not reach here because it will execute the previous if and exit
403  else if (previous >= phyHeaderStart)
404  {
405  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
406  //Case 4a: current after payload start
407  if (current >= phyPayloadStart)
408  {
409  psr *= CalculateChunkSuccessRate (snr, phyLSigHeaderEnd - previous, headerMode, txVector);
410  NS_LOG_DEBUG ("Case 4a - previous in L-SIG and current after payload start: mode=" << headerMode << ", psr=" << psr);
411  }
412  //Case 4b: current is in training or in SIG-B. non-HT will not come here since it went in previous if or if the previous if is not true this will be not true
413  else if (current >= phyTrainingSymbolsStart)
414  {
415  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
416  psr *= CalculateChunkSuccessRate (snr, phyLSigHeaderEnd - previous, headerMode, txVector);
417  NS_LOG_DEBUG ("Case 4a - previous in L-SIG and current is in training or in SIG-B: mode=" << headerMode << ", psr=" << psr);
418  }
419  //Case 4c: current in HT-SIG or in SIG-A. non-HT will not come here since it went in previous if or if the previous if is not true this will be not true
420  else if (current >= phyLSigHeaderEnd)
421  {
422  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
423  psr *= CalculateChunkSuccessRate (snr, phyLSigHeaderEnd - previous, headerMode, txVector);
424  NS_LOG_DEBUG ("Case 4ci - previous is in L-SIG and current in HT-SIG or in SIG-A: mode=" << headerMode << ", psr=" << psr);
425  }
426  //Case 4d: current with previous in L-SIG
427  else
428  {
429  psr *= CalculateChunkSuccessRate (snr, current - previous, headerMode, txVector);
430  NS_LOG_DEBUG ("Case 4d - current with previous in L-SIG: mode=" << headerMode << ", psr=" << psr);
431  }
432  }
433  //Case 5: previous is in the preamble works for all cases
434  else
435  {
436  //Case 5a: current after payload start
437  if (current >= phyPayloadStart)
438  {
439  psr *= CalculateChunkSuccessRate (snr, phyLSigHeaderEnd - phyHeaderStart, headerMode, txVector);
440  NS_LOG_DEBUG ("Case 5aii - previous is in the preamble and current is after payload start: mode=" << headerMode << ", psr=" << psr);
441  }
442  //Case 5b: current is in training or in SIG-B. non-HT will not come here since it went in previous if or if the previous if is not true this will be not true
443  else if (current >= phyTrainingSymbolsStart)
444  {
445  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
446  psr *= CalculateChunkSuccessRate (snr, phyLSigHeaderEnd - phyHeaderStart, headerMode, txVector);
447  NS_LOG_DEBUG ("Case 5b - previous is in the preamble and current is in training or in SIG-B: mode=" << headerMode << ", psr=" << psr);
448  }
449  //Case 5c: current in HT-SIG or in SIG-A. non-HT will not come here since it went in previous if or if the previous if is not true this will be not true
450  else if (current >= phyLSigHeaderEnd)
451  {
452  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
453  psr *= CalculateChunkSuccessRate (snr, phyLSigHeaderEnd - phyHeaderStart, headerMode, txVector);
454  NS_LOG_DEBUG ("Case 5b - previous is in the preamble and current in HT-SIG or in SIG-A: mode=" << headerMode << ", psr=" << psr);
455  }
456  //Case 5d: current is in L-SIG.
457  else if (current >= phyHeaderStart)
458  {
459  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
460  psr *= CalculateChunkSuccessRate (snr, current - phyHeaderStart, headerMode, txVector);
461  NS_LOG_DEBUG ("Case 5d - previous is in the preamble and current is in L-SIG: mode=" << headerMode << ", psr=" << psr);
462  }
463  }
464 
465  noiseInterferenceW = j->second.GetPower () - powerW;
466  previous = j->first;
467  }
468 
469  double per = 1 - psr;
470  return per;
471 }
472 
473 double
475 {
476  NS_LOG_FUNCTION (this);
477  const WifiTxVector txVector = event->GetTxVector ();
478  double psr = 1.0; /* Packet Success Rate */
479  auto j = ni->begin ();
480  Time previous = j->first;
481  WifiPreamble preamble = txVector.GetPreambleType ();
482  WifiMode mcsHeaderMode;
483  if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF)
484  {
485  //mode for PHY header fields sent with HT modulation
486  mcsHeaderMode = WifiPhy::GetHtPhyHeaderMode ();
487  }
488  else if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_VHT_MU)
489  {
490  //mode for PHY header fields sent with VHT modulation
491  mcsHeaderMode = WifiPhy::GetVhtPhyHeaderMode ();
492  }
493  else if (preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_HE_MU)
494  {
495  //mode for PHY header fields sent with HE modulation
496  mcsHeaderMode = WifiPhy::GetHePhyHeaderMode ();
497  }
498  WifiMode headerMode = WifiPhy::GetPhyHeaderMode (txVector);
499  Time phyHeaderStart = j->first + WifiPhy::GetPhyPreambleDuration (txVector); //PPDU start time + preamble
500  Time phyLSigHeaderEnd = phyHeaderStart + WifiPhy::GetPhyHeaderDuration (txVector); //PPDU start time + preamble + L-SIG
501  Time phyTrainingSymbolsStart = phyLSigHeaderEnd + WifiPhy::GetPhyHtSigHeaderDuration (preamble) + WifiPhy::GetPhySigA1Duration (preamble) + WifiPhy::GetPhySigA2Duration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A
502  Time phyPayloadStart = phyTrainingSymbolsStart + WifiPhy::GetPhyTrainingSymbolDuration (txVector) + WifiPhy::GetPhySigBDuration (preamble); //PPDU start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
503  double noiseInterferenceW = m_firstPower;
504  double powerW = event->GetRxPowerW ();
505  while (++j != ni->end ())
506  {
507  Time current = j->first;
508  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
509  NS_ASSERT (current >= previous);
510  double snr = CalculateSnr (powerW, noiseInterferenceW, txVector.GetChannelWidth ());
511  //Case 1: previous and current after payload start: nothing to do
512  if (previous >= phyPayloadStart)
513  {
514  psr *= 1;
515  NS_LOG_DEBUG ("Case 1 - previous and current after payload start: nothing to do");
516  }
517  //Case 2: previous is in training or in SIG-B: non-HT will not enter here since it didn't enter in the last two and they are all the same for non-HT
518  else if (previous >= phyTrainingSymbolsStart)
519  {
520  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
521  //Case 2a: current after payload start
522  if (current >= phyPayloadStart)
523  {
524  psr *= CalculateChunkSuccessRate (snr, phyPayloadStart - previous, mcsHeaderMode, txVector);
525  NS_LOG_DEBUG ("Case 2a - previous is in training or in SIG-B and current after payload start: mode=" << mcsHeaderMode << ", psr=" << psr);
526  }
527  //Case 2b: current is in training or in SIG-B
528  else
529  {
530  psr *= CalculateChunkSuccessRate (snr, current - previous, mcsHeaderMode, txVector);
531  NS_LOG_DEBUG ("Case 2b - previous is in training or in SIG-B and current is in training or in SIG-B: mode=" << mcsHeaderMode << ", psr=" << psr);
532  }
533  }
534  //Case 3: previous is in HT-SIG or SIG-A: non-HT will not enter here since it didn't enter in the last two and they are all the same for non-HT
535  else if (previous >= phyLSigHeaderEnd)
536  {
537  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
538  //Case 3a: current after payload start
539  if (current >= phyPayloadStart)
540  {
541  psr *= CalculateChunkSuccessRate (snr, phyPayloadStart - phyTrainingSymbolsStart, mcsHeaderMode, txVector);
542  //Case 3ai: VHT or HE format
543  if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
544  {
545  //SIG-A is sent using non-HT OFDM modulation
546  psr *= CalculateChunkSuccessRate (snr, phyTrainingSymbolsStart - previous, headerMode, txVector);
547  NS_LOG_DEBUG ("Case 3ai - previous is in SIG-A and current after payload start: mcs mode=" << mcsHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
548  }
549  //Case 3aii: HT formats
550  else
551  {
552  psr *= CalculateChunkSuccessRate (snr, phyTrainingSymbolsStart - previous, mcsHeaderMode, txVector);
553  NS_LOG_DEBUG ("Case 3aii - previous is in HT-SIG and current after payload start: mode=" << mcsHeaderMode << ", psr=" << psr);
554  }
555  }
556  //Case 3b: current is in training or in SIG-B
557  else if (current >= phyTrainingSymbolsStart)
558  {
559  psr *= CalculateChunkSuccessRate (snr, current - phyTrainingSymbolsStart, mcsHeaderMode, txVector);
560  //Case 3bi: VHT or HE format
561  if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
562  {
563  //SIG-A is sent using non-HT OFDM modulation
564  psr *= CalculateChunkSuccessRate (snr, phyTrainingSymbolsStart - previous, headerMode, txVector);
565  NS_LOG_DEBUG ("Case 3bi - previous is in SIG-A and current is in training or in SIG-B: mode=" << headerMode << ", psr=" << psr);
566  }
567  //Case 3bii: HT formats
568  else
569  {
570  psr *= CalculateChunkSuccessRate (snr, phyTrainingSymbolsStart - previous, mcsHeaderMode, txVector);
571  NS_LOG_DEBUG ("Case 3bii - previous is in HT-SIG and current is in HT training: mode=" << mcsHeaderMode << ", psr=" << psr);
572  }
573  }
574  //Case 3c: current with previous in HT-SIG or SIG-A
575  else
576  {
577  //Case 3ci: VHT or HE format
578  if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
579  {
580  //SIG-A is sent using non-HT OFDM modulation
581  psr *= CalculateChunkSuccessRate (snr, current - previous, headerMode, txVector);
582  NS_LOG_DEBUG ("Case 3ci - previous with current in SIG-A: mode=" << headerMode << ", psr=" << psr);
583  }
584  //Case 3cii: HT mixed format or HT greenfield
585  else
586  {
587  psr *= CalculateChunkSuccessRate (snr, current - previous, mcsHeaderMode, txVector);
588  NS_LOG_DEBUG ("Case 3cii - previous with current in HT-SIG: mode=" << mcsHeaderMode << ", psr=" << psr);
589  }
590  }
591  }
592  //Case 4: previous in L-SIG: HT GF will not reach here because it will execute the previous if and exit
593  else if (previous >= phyHeaderStart)
594  {
595  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
596  //Case 4a: current after payload start
597  if (current >= phyPayloadStart)
598  {
599  //Case 4ai: non-HT format
600  if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
601  {
602  psr *= 1;
603  NS_LOG_DEBUG ("Case 4ai - previous in L-SIG and current after payload start: nothing to do");
604  }
605  //Case 4aii: VHT or HE format
606  else if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
607  {
608  psr *= CalculateChunkSuccessRate (snr, phyPayloadStart - phyTrainingSymbolsStart, mcsHeaderMode, txVector);
609  psr *= CalculateChunkSuccessRate (snr, phyTrainingSymbolsStart - phyLSigHeaderEnd, headerMode, txVector);
610  NS_LOG_DEBUG ("Case 4aii - previous is in L-SIG and current after payload start: mcs mode=" << mcsHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
611  }
612  //Case 4aiii: HT mixed format
613  else
614  {
615  psr *= CalculateChunkSuccessRate (snr, phyPayloadStart - phyLSigHeaderEnd, mcsHeaderMode, txVector);
616  NS_LOG_DEBUG ("Case 4aiii - previous in L-SIG and current after payload start: mcs mode=" << mcsHeaderMode << ", psr=" << psr);
617  }
618  }
619  //Case 4b: current is in training or in SIG-B. non-HT will not come here since it went in previous if or if the previous if is not true this will be not true
620  else if (current >= phyTrainingSymbolsStart)
621  {
622  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
623  //Case 4bi: VHT or HE format
624  if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
625  {
626  psr *= CalculateChunkSuccessRate (snr, current - phyTrainingSymbolsStart, mcsHeaderMode, txVector);
627  psr *= CalculateChunkSuccessRate (snr, phyTrainingSymbolsStart - phyLSigHeaderEnd, headerMode, txVector);
628  NS_LOG_DEBUG ("Case 4bi - previous is in L-SIG and current in training or in SIG-B: mcs mode=" << mcsHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
629  }
630  //Case 4bii: HT mixed format
631  else
632  {
633  psr *= CalculateChunkSuccessRate (snr, current - phyLSigHeaderEnd, mcsHeaderMode, txVector);
634  NS_LOG_DEBUG ("Case 4bii - previous in L-SIG and current in HT training: mcs mode=" << mcsHeaderMode << ", psr=" << psr);
635  }
636  }
637  //Case 4c: current in HT-SIG or in SIG-A. Non-HT will not come here since it went in previous if or if the previous if is not true this will be not true
638  else if (current >= phyLSigHeaderEnd)
639  {
640  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
641  //Case 4ci: VHT format
642  if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
643  {
644  psr *= CalculateChunkSuccessRate (snr, current - phyLSigHeaderEnd, headerMode, txVector);
645  NS_LOG_DEBUG ("Case 4ci - previous is in L-SIG and current in SIG-A: mode=" << headerMode << ", psr=" << psr);
646  }
647  //Case 4cii: HT mixed format
648  else
649  {
650  psr *= CalculateChunkSuccessRate (snr, current - phyLSigHeaderEnd, mcsHeaderMode, txVector);
651  NS_LOG_DEBUG ("Case 4cii - previous in L-SIG and current in HT-SIG: mcs mode=" << mcsHeaderMode << ", psr=" << psr);
652  }
653  }
654  //Case 4d: current with previous in L-SIG
655  else
656  {
657  psr *= 1;
658  NS_LOG_DEBUG ("Case 4d - current with previous in L-SIG: nothing to do");
659  }
660  }
661  //Case 5: previous is in the preamble works for all cases
662  else
663  {
664  //Case 5a: current after payload start
665  if (current >= phyPayloadStart)
666  {
667  //Case 5ai: non-HT format (No HT-SIG or Training Symbols)
668  if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
669  {
670  psr *= 1;
671  NS_LOG_DEBUG ("Case 5ai - previous is in the preamble and current is after payload start: nothing to do");
672  }
673  //Case 5aii: VHT or HE format
674  else if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
675  {
676  psr *= CalculateChunkSuccessRate (snr, phyPayloadStart - phyTrainingSymbolsStart, mcsHeaderMode, txVector);
677  psr *= CalculateChunkSuccessRate (snr, phyTrainingSymbolsStart - phyLSigHeaderEnd, headerMode, txVector);
678  NS_LOG_DEBUG ("Case 5aii - previous is in the preamble and current is after payload start: mcs mode=" << mcsHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
679  }
680  //Case 5aiii: HT formats
681  else
682  {
683  psr *= CalculateChunkSuccessRate (snr, phyPayloadStart - phyLSigHeaderEnd, mcsHeaderMode, txVector);
684  NS_LOG_DEBUG ("Case 5aiii - previous is in the preamble and current is after payload start: mcs mode=" << mcsHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
685  }
686  }
687  //Case 5b: current is in training or in SIG-B. Non-HT will not come here since it went in previous if or if the previous if is not true this will be not true
688  else if (current >= phyTrainingSymbolsStart)
689  {
690  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
691  //Case 5bi: VHT or HE format
692  if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
693  {
694  psr *= CalculateChunkSuccessRate (snr, current - phyTrainingSymbolsStart, mcsHeaderMode, txVector);
695  psr *= CalculateChunkSuccessRate (snr, phyTrainingSymbolsStart - phyLSigHeaderEnd, headerMode, txVector);
696  NS_LOG_DEBUG ("Case 5bi - previous is in the preamble and current in training or in SIG-B: mcs mode=" << mcsHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
697  }
698  //Case 5bii: HT mixed format
699  else
700  {
701  psr *= CalculateChunkSuccessRate (snr, current - phyLSigHeaderEnd, mcsHeaderMode, txVector);
702  NS_LOG_DEBUG ("Case 5bii - previous is in the preamble and current in HT training: mcs mode=" << mcsHeaderMode << ", psr=" << psr);
703  }
704  }
705  //Case 5c: current in HT-SIG or in SIG-A. Non-HT will not come here since it went in previous if or if the previous if is not true this will be not true
706  else if (current >= phyLSigHeaderEnd)
707  {
708  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
709  //Case 5ci: VHT or HE format
710  if (preamble == WIFI_PREAMBLE_VHT_SU || preamble == WIFI_PREAMBLE_HE_SU || preamble == WIFI_PREAMBLE_VHT_MU || preamble == WIFI_PREAMBLE_HE_MU)
711  {
712  psr *= CalculateChunkSuccessRate (snr, current - phyLSigHeaderEnd, headerMode, txVector);
713  NS_LOG_DEBUG ("Case 5ci - previous is in preamble and current in SIG-A: mode=" << headerMode << ", psr=" << psr);
714  }
715  //Case 5cii: HT formats
716  else
717  {
718  psr *= CalculateChunkSuccessRate (snr, current - phyLSigHeaderEnd, mcsHeaderMode, txVector);
719  NS_LOG_DEBUG ("Case 5cii - previous in preamble and current in HT-SIG: mcs mode=" << mcsHeaderMode << ", psr=" << psr);
720  }
721  }
722  //Case 5d: current is in L-SIG. HT-GF will not come here
723  else if (current >= phyHeaderStart)
724  {
725  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
726  psr *= 1;
727  NS_LOG_DEBUG ("Case 5d - previous is in the preamble and current is in L-SIG: nothing to do");
728  }
729  }
730 
731  noiseInterferenceW = j->second.GetPower () - powerW;
732  previous = j->first;
733  }
734 
735  double per = 1 - psr;
736  return per;
737 }
738 
740 InterferenceHelper::CalculatePayloadSnrPer (Ptr<Event> event, std::pair<Time, Time> relativeMpduStartStop) const
741 {
742  NiChanges ni;
743  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
744  double snr = CalculateSnr (event->GetRxPowerW (),
745  noiseInterferenceW,
746  event->GetTxVector ().GetChannelWidth ());
747 
748  /* calculate the SNIR at the start of the MPDU (located through windowing) and accumulate
749  * all SNIR changes in the SNIR vector.
750  */
751  double per = CalculatePayloadPer (event, &ni, relativeMpduStartStop);
752 
753  struct SnrPer snrPer;
754  snrPer.snr = snr;
755  snrPer.per = per;
756  return snrPer;
757 }
758 
759 double
761 {
762  NiChanges ni;
763  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
764  double snr = CalculateSnr (event->GetRxPowerW (),
765  noiseInterferenceW,
766  event->GetTxVector ().GetChannelWidth ());
767  return snr;
768 }
769 
771 InterferenceHelper::CalculateNonHtPhyHeaderSnrPer (Ptr<Event> event) const
772 {
773  NiChanges ni;
774  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
775  double snr = CalculateSnr (event->GetRxPowerW (),
776  noiseInterferenceW,
777  event->GetTxVector ().GetChannelWidth ());
778 
779  /* calculate the SNIR at the start of the PHY header and accumulate
780  * all SNIR changes in the SNIR vector.
781  */
782  double per = CalculateNonHtPhyHeaderPer (event, &ni);
783 
784  struct SnrPer snrPer;
785  snrPer.snr = snr;
786  snrPer.per = per;
787  return snrPer;
788 }
789 
791 InterferenceHelper::CalculateHtPhyHeaderSnrPer (Ptr<Event> event) const
792 {
793  NiChanges ni;
794  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
795  double snr = CalculateSnr (event->GetRxPowerW (),
796  noiseInterferenceW,
797  event->GetTxVector ().GetChannelWidth ());
798 
799  /* calculate the SNIR at the start of the PHY header and accumulate
800  * all SNIR changes in the SNIR vector.
801  */
802  double per = CalculateHtPhyHeaderPer (event, &ni);
803 
804  struct SnrPer snrPer;
805  snrPer.snr = snr;
806  snrPer.per = per;
807  return snrPer;
808 }
809 
810 void
812 {
813  m_niChanges.clear ();
814  // Always have a zero power noise event in the list
815  AddNiChangeEvent (Time (0), NiChange (0.0, 0));
816  m_rxing = false;
817  m_firstPower = 0;
818 }
819 
820 InterferenceHelper::NiChanges::const_iterator
822 {
823  return m_niChanges.upper_bound (moment);
824 }
825 
826 InterferenceHelper::NiChanges::const_iterator
828 {
829  auto it = GetNextPosition (moment);
830  // This is safe since there is always an NiChange at time 0,
831  // before moment.
832  --it;
833  return it;
834 }
835 
836 InterferenceHelper::NiChanges::iterator
838 {
839  return m_niChanges.insert (GetNextPosition (moment), std::make_pair (moment, change));
840 }
841 
842 void
844 {
845  NS_LOG_FUNCTION (this);
846  m_rxing = true;
847 }
848 
849 void
851 {
852  NS_LOG_FUNCTION (this);
853  m_rxing = false;
854  //Update m_firstPower for frame capture
855  auto it = GetPreviousPosition (Simulator::Now ());
856  it--;
857  m_firstPower = it->second.GetPower ();
858 }
859 
860 } //namespace ns3
double GetRxPowerW(void) const
Return the received power (w).
void AddPower(double power)
Add a given amount of power.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
void AddForeignSignal(Time duration, double rxPower)
Add a non-Wifi signal to interference helper.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
NiChanges::iterator AddNiChangeEvent(Time moment, NiChange change)
Add NiChange to the list at the appropriate position and return the iterator of the new event...
Control the scheduling of simulation events.
Definition: simulator.h:68
void SetNumberOfReceiveAntennas(uint8_t rx)
Set the number of RX antennas in the receiver corresponding to this interference helper.
double m_rxPowerW
received power in watts
Definition: second.py:1
Ptr< ErrorRateModel > GetErrorRateModel(void) const
Return the error rate model.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
Time GetEndTime(void) const
Return the end time of the signal.
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
handles interference calculations
double CalculateNonHtPhyHeaderPer(Ptr< const Event > event, NiChanges *ni) const
Calculate the error rate of the non-HT PHY header.
static WifiMode GetHePhyHeaderMode()
Definition: wifi-phy.cc:1785
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:355
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
void SetErrorRateModel(const Ptr< ErrorRateModel > rate)
Set the error rate model for this interference helper.
static Time GetPhyPreambleDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:2051
Time GetStartTime(void) const
Return the start time of the signal.
Ptr< Event > GetEvent(void) const
Return the event causes the corresponding NI change.
Ptr< const WifiPpdu > GetPpdu(void) const
Return the PPDU.
Ptr< ErrorRateModel > m_errorRateModel
error rate model
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
double snr
SNR in linear scale.
Ptr< const WifiPpdu > m_ppdu
PPDU.
double CalculateChunkSuccessRate(double snir, Time duration, WifiMode mode, WifiTxVector txVector) const
Calculate the success rate of the chunk given the SINR, duration, and Wi-Fi mode. ...
WifiPreamble GetPreambleType(void) const
static Time GetPhyHtSigHeaderDuration(WifiPreamble preamble)
Definition: wifi-phy.cc:1846
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
Definition: wifi-preamble.h:32
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:197
static WifiMode GetHtPhyHeaderMode()
Definition: wifi-phy.cc:1773
bool IsZero(void) const
Definition: nstime.h:288
Time GetEnergyDuration(double energyW) const
NiChanges m_niChanges
Experimental: needed for energy duration calculation.
double CalculatePayloadChunkSuccessRate(double snir, Time duration, WifiTxVector txVector) const
Calculate the success rate of the payload chunk given the SINR, duration, and Wi-Fi mode...
Time GetDuration(void) const
Return the duration of the signal.
WifiMode GetMode(void) const
HT PHY (Clause 20)
Definition: wifi-mode.h:58
uint8_t GetNTx(void) const
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:463
double CalculateNoiseInterferenceW(Ptr< Event > event, NiChanges *ni) const
Calculate noise and interference power in W.
WifiTxVector GetTxVector(void) const
Return the TXVECTOR of the PPDU.
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
static WifiMode GetVhtPhyHeaderMode()
Definition: wifi-phy.cc:1779
double m_noiseFigure
noise figure (linear)
static Time GetPhySigA1Duration(WifiPreamble preamble)
Definition: wifi-phy.cc:1861
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void NotifyRxStart()
Notify that RX has started.
Noise and Interference (thus Ni) event.
void EraseEvents(void)
Erase all events.
static Time GetPhyTrainingSymbolDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:1797
double CalculateSnr(Ptr< Event > event) const
Calculate the SNIR for the event (starting from now until the event end).
uint8_t m_numRxAntennas
the number of RX antennas in the corresponding receiver
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:193
double CalculateHtPhyHeaderPer(Ptr< const Event > event, NiChanges *ni) const
Calculate the error rate of the HT PHY header.
Ptr< Event > Add(Ptr< const WifiPpdu > ppdu, WifiTxVector txVector, Time duration, double rxPower)
Add the PPDU-related signal to interference helper.
double RatioToDb(double ratio)
Convert from ratio to dB.
Definition: wifi-utils.cc:53
static WifiMode GetPhyHeaderMode(WifiTxVector txVector)
Definition: wifi-phy.cc:1909
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Event(Ptr< const WifiPpdu > ppdu, WifiTxVector txVector, Time duration, double rxPower)
Create an Event with the given parameters.
void NotifyRxEnd()
Notify that RX has ended.
void SetNoiseFigure(double value)
Set the noise figure.
double m_firstPower
first power in watts
NiChange(double power, Ptr< Event > event)
Create a NiChange at the given time and the amount of NI change.
double CalculatePayloadPer(Ptr< const Event > event, NiChanges *ni, std::pair< Time, Time > window) const
Calculate the error rate of the given PHY payload only in the provided time window (thus enabling per...
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
static Time GetPhySigA2Duration(WifiPreamble preamble)
Definition: wifi-phy.cc:1878
WifiTxVector m_txVector
TXVECTOR.
void AppendEvent(Ptr< Event > event)
Append the given Event.
Time m_endTime
end time
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1080
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:309
NiChanges::const_iterator GetNextPosition(Time moment) const
Returns an iterator to the first NiChange that is later than moment.
double GetPower(void) const
Return the power.
uint16_t GetChannelWidth(void) const
static Time GetPhyHeaderDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:1973
handles interference calculations
Ptr< const WifiPsdu > GetPsdu(void) const
Return the PSDU in the PPDU.
Definition: first.py:1
static Time GetPhySigBDuration(WifiPreamble preamble)
Definition: wifi-phy.cc:1895
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:119
Implements the IEEE 802.11 MAC header.
NiChanges::const_iterator GetPreviousPosition(Time moment) const
Returns an iterator to the first NiChange that is later than moment.
uint8_t GetNss(void) const
std::multimap< Time, NiChange > NiChanges
typedef for a multimap of NiChanges
bool m_rxing
flag whether it is in receiving state
Time m_startTime
start time